-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathVyperDeployer.sol
130 lines (106 loc) · 5.19 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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.13;
///@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);
}
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);
///@notice Compiles a Vyper contract and returns the address that the contract was deployeod to
///@notice If deployment fails, an error will be thrown
///@param fileName - The file name of the Vyper contract. For example, the file name for "SimpleStore.vy" is "SimpleStore"
///@return deployedAddress - The address that the contract was deployed to
function deployContract(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("vyper_contracts/", 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;
}
///@notice Compiles a Vyper contract with constructor arguments and returns the address that the contract was deployeod to
///@notice If deployment fails, an error will be thrown
///@param fileName - The file name of the Vyper contract. For example, the file name for "SimpleStore.vy" is "SimpleStore"
///@return deployedAddress - The address that the contract was deployed to
function deployContract(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("vyper_contracts/", 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;
}
/// @dev Consider listening to the Blueprint if you haven't already
/// @param fileName - The file name of the Blueprint Contract
function deployBlueprint(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("vyper_contracts/", fileName, ".vy");
///@notice compile the Vyper contract and return the bytecode
bytes memory bytecode = cheatCodes.ffi(cmds);
require(
bytecode.length > 0,
"Initcodes length must be greater than 0"
);
/// @notice prepend needed items for Blueprint ERC
/// See https://eips.ethereum.org/EIPS/eip-5202 for more details
bytes memory eip_5202_bytecode = bytes.concat(
hex"fe", // EIP_5202_EXECUTION_HALT_BYTE
hex"71", // EIP_5202_BLUEPRINT_IDENTIFIER_BYTE
hex"00", // EIP_5202_VERSION_BYTE
bytecode
);
bytes2 len = bytes2(uint16(eip_5202_bytecode.length));
/// @notice prepend the deploy preamble
bytes memory deployBytecode = bytes.concat(
hex"61", // DEPLOY_PREAMBLE_INITIAL_BYTE
len, // DEPLOY_PREAMBLE_BYTE_LENGTH
hex"3d81600a3d39f3", // DEPLOY_PREABLE_POST_LENGTH_BYTES
eip_5202_bytecode
);
///@notice check that the deployment was successful
address deployedAddress;
assembly {
deployedAddress := create(0, add(deployBytecode, 0x20), mload(deployBytecode))
}
require(
deployedAddress != address(0),
"VyperDeployer could not deploy contract"
);
///@notice return the address that the contract was deployed to
return deployedAddress;
}
}