-
Notifications
You must be signed in to change notification settings - Fork 0
/
VyperDeployer.sol
101 lines (86 loc) · 3.89 KB
/
VyperDeployer.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
///@notice This cheat codes interface is named _CheatCodes so you can use the CheatCodes interface in other testing files without errors
interface _CheatCodes {
function ffi(string[] calldata) external returns (bytes memory);
}
/**
* @title Vyper Contract Deployer
* @notice Forked and modified from here:
* https://github.com/pcaversaccio/snekmate/blob/main/lib/utils/VyperDeployer.sol
* @dev The Vyper deployer is a pre-built contract that takes a filename
* and deploys the corresponding Vyper contract, returning the address
* that the bytecode was deployed to.
*/
contract VyperDeployer {
address constant HEVM_ADDRESS =
address(bytes20(uint160(uint256(keccak256("hevm cheat code")))));
/// @notice Initializes cheat codes in order to use ffi to compile Vyper contracts
_CheatCodes cheatCodes = _CheatCodes(HEVM_ADDRESS);
/**
* @dev Compiles a Vyper contract and returns the address that the contract
* was deployed to. If the deployment fails, an error is thrown.
* @param path The directory path of the Vyper contract.
* For example, the path of "test" is "src/test/".
* @param fileName The file name of the Vyper contract.
* For example, the file name for "Token.vy" is "Token".
* @return deployedAddress The address that the contract was deployed to.
*/
function deployContract(string memory path, string memory fileName)
public
returns (address) {
///@notice create a list of strings with the commands necessary to compile Vyper contracts
string[] memory cmds = new string[](2);
cmds[0] = "vyper";
cmds[1] = string.concat(path, fileName, ".vy");
///@notice compile the Vyper contract and return the bytecode
bytes memory bytecode = cheatCodes.ffi(cmds);
///@notice deploy the bytecode with the create instruction
address deployedAddress;
assembly {
deployedAddress := create(0, add(bytecode, 0x20), mload(bytecode))
}
///@notice check that the deployment was successful
require(
deployedAddress != address(0),
"VyperDeployer could not deploy contract"
);
///@notice return the address that the contract was deployed to
return deployedAddress;
}
/**
* @dev Compiles a Vyper contract and returns the address that the contract
* was deployed to. If the deployment fails, an error is thrown.
* @param path The directory path of the Vyper contract.
* For example, the path of "test" is "src/test/".
* @param fileName The file name of the Vyper contract.
* For example, the file name for "Token.vy" is "Token".
* @return deployedAddress The address that the contract was deployed to.
*/
function deployContract(
string memory path,
string memory fileName,
bytes calldata args
) public returns (address) {
///@notice create a list of strings with the commands necessary to compile Vyper contracts
string[] memory cmds = new string[](2);
cmds[0] = "vyper";
cmds[1] = string.concat(path, fileName, ".vy");
///@notice compile the Vyper contract and return the bytecode
bytes memory _bytecode = cheatCodes.ffi(cmds);
//add args to the deployment bytecode
bytes memory bytecode = abi.encodePacked(_bytecode, args);
///@notice deploy the bytecode with the create instruction
address deployedAddress;
assembly {
deployedAddress := create(0, add(bytecode, 0x20), mload(bytecode))
}
///@notice check that the deployment was successful
require(
deployedAddress != address(0),
"VyperDeployer could not deploy contract"
);
///@notice return the address that the contract was deployed to
return deployedAddress;
}
}