Address Contract Partially Verified
Address
0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed
Balance
0 ETH
Nonce
2597
Code Size
11838 bytes
Creator
0xeD456e05...52b5 at tx 0xceec66d7...6113e1
Indexed Transactions
0
Contract Bytecode
11838 bytes
0x60806040526004361061018a5760003560e01c806381503da1116100d6578063d323826a1161007f578063e96deee411610059578063e96deee414610395578063f5745aba146103a8578063f9664498146103bb57600080fd5b8063d323826a1461034f578063ddda0acb1461036f578063e437252a1461038257600080fd5b80639c36a286116100b05780639c36a28614610316578063a7db93f214610329578063c3fe107b1461033c57600080fd5b806381503da1146102d0578063890c283b146102e357806398e810771461030357600080fd5b80632f990e3f116101385780636cec2536116101125780636cec25361461027d57806374637a7a1461029d5780637f565360146102bd57600080fd5b80632f990e3f1461023757806331a7c8c81461024a57806342d654fc1461025d57600080fd5b806327fe18221161016957806327fe1822146101f15780632852527a1461020457806328ddd0461461021757600080fd5b8062d84acb1461018f57806326307668146101cb57806326a32fc7146101de575b600080fd5b6101a261019d366004612915565b6103ce565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6101a26101d9366004612994565b6103e6565b6101a26101ec3660046129db565b610452565b6101a26101ff3660046129db565b6104de565b6101a2610212366004612a39565b610539565b34801561022357600080fd5b506101a2610232366004612a90565b6106fe565b6101a2610245366004612aa9565b61072a565b6101a2610258366004612aa9565b6107bb565b34801561026957600080fd5b506101a2610278366004612b1e565b6107c9565b34801561028957600080fd5b506101a2610298366004612a90565b610823565b3480156102a957600080fd5b506101a26102b8366004612b4a565b61084f565b6101a26102cb3660046129db565b611162565b6101a26102de366004612b74565b6111e8565b3480156102ef57600080fd5b506101a26102fe366004612bac565b611276565b6101a2610311366004612bce565b6112a3565b6101a2610324366004612994565b611505565b6101a2610337366004612c49565b6116f1565b6101a261034a366004612aa9565b611964565b34801561035b57600080fd5b506101a261036a366004612cd9565b6119ed565b6101a261037d366004612c49565b611a17565b6101a2610390366004612bce565b611e0c565b6101a26103a3366004612915565b611e95565b6101a26103b6366004612bce565b611ea4565b6101a26103c9366004612b74565b611f2d565b60006103dd8585858533611a17565b95945050505050565b6000806103f2846120db565b90508083516020850134f59150610408826123d3565b604051819073ffffffffffffffffffffffffffffffffffffffff8416907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a35092915050565b60006104d86104d260408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b836103e6565b92915050565b600081516020830134f090506104f3816123d3565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a2919050565b600080610545856120db565b905060008460601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f593505073ffffffffffffffffffffffffffffffffffffffff8316610635576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed1660048201526024015b60405180910390fd5b604051829073ffffffffffffffffffffffffffffffffffffffff8516907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a36000808473ffffffffffffffffffffffffffffffffffffffff1634876040516106a19190612d29565b60006040518083038185875af1925050503d80600081146106de576040519150601f19603f3d011682016040523d82523d6000602084013e6106e3565b606091505b50915091506106f382828961247d565b505050509392505050565b60006104d87f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed8361084f565b60006107b36107aa60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b85858533611a17565b949350505050565b60006107b3848484336112a3565b60006040518260005260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d694600052600160345350506017601e20919050565b60006104d8827f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed6107c9565b600060607f9400000000000000000000000000000000000000000000000000000000000000610887600167ffffffffffffffff612d45565b67ffffffffffffffff16841115610902576040517f3c55ab3b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b836000036109c7576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f800000000000000000000000000000000000000000000000000000000000000060368201526037015b6040516020818303038152906040529150611152565b607f8411610a60576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527fff0000000000000000000000000000000000000000000000000000000000000080831660218301527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16602283015260f886901b1660368201526037016109b1565b60ff8411610b1f576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527fff0000000000000000000000000000000000000000000000000000000000000080831660218301527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660228301527f8100000000000000000000000000000000000000000000000000000000000000603683015260f886901b1660378201526038016109b1565b61ffff8411610bff576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f086901b1660378201526039016109b1565b62ffffff8411610ce0576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e886901b166037820152603a016109b1565b63ffffffff8411610dc2576040517fda0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e086901b166037820152603b016109b1565b64ffffffffff8411610ea5576040517fdb0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f850000000000000000000000000000000000000000000000000000000000000060368201527fffffffffff00000000000000000000000000000000000000000000000000000060d886901b166037820152603c016109b1565b65ffffffffffff8411610f89576040517fdc0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f860000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffff000000000000000000000000000000000000000000000000000060d086901b166037820152603d016109b1565b66ffffffffffffff841161106e576040517fdd0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f870000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffffff0000000000000000000000000000000000000000000000000060c886901b166037820152603e016109b1565b6040517fde0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f880000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffffffff00000000000000000000000000000000000000000000000060c086901b166037820152603f0160405160208183030381529060405291505b5080516020909101209392505050565b60006104d86111e260408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b83611505565b600061126f61126860408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b8484610539565b9392505050565b600061126f83837f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed6119ed565b60008451602086018451f090506112b9816123d3565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a26000808273ffffffffffffffffffffffffffffffffffffffff168560200151876040516113279190612d29565b60006040518083038185875af1925050503d8060008114611364576040519150601f19603f3d011682016040523d82523d6000602084013e611369565b606091505b5091509150816113c9577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed1631156114fb578373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d8060008114611495576040519150601f19603f3d011682016040523d82523d6000602084013e61149a565b606091505b509092509050816114fb577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b5050949350505050565b600080611511846120db565b905060006040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000828251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff81166115e0576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b604051839073ffffffffffffffffffffffffffffffffffffffff8316907f2feea65dd4e9f9cbd86b74b7734210c59a1b2981b5b137bd0ee3e208200c906790600090a361162c83610823565b935060008173ffffffffffffffffffffffffffffffffffffffff1634876040516116569190612d29565b60006040518083038185875af1925050503d8060008114611693576040519150601f19603f3d011682016040523d82523d6000602084013e611698565b606091505b505090506116a681866124ff565b60405173ffffffffffffffffffffffffffffffffffffffff8616907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a25050505092915050565b6000806116fd876120db565b9050808651602088018651f59150611714826123d3565b604051819073ffffffffffffffffffffffffffffffffffffffff8416907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a36000808373ffffffffffffffffffffffffffffffffffffffff168660200151886040516117849190612d29565b60006040518083038185875af1925050503d80600081146117c1576040519150601f19603f3d011682016040523d82523d6000602084013e6117c6565b606091505b509150915081611826577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed163115611958578473ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d80600081146118f2576040519150601f19603f3d011682016040523d82523d6000602084013e6118f7565b606091505b50909250905081611958577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b50505095945050505050565b60006107b36119e460408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b858585336116f1565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b600080611a23876120db565b905060006040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000828251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff8116611af2576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b604051839073ffffffffffffffffffffffffffffffffffffffff8316907f2feea65dd4e9f9cbd86b74b7734210c59a1b2981b5b137bd0ee3e208200c906790600090a3611b3e83610823565b935060008173ffffffffffffffffffffffffffffffffffffffff1687600001518a604051611b6c9190612d29565b60006040518083038185875af1925050503d8060008114611ba9576040519150601f19603f3d011682016040523d82523d6000602084013e611bae565b606091505b50509050611bbc81866124ff565b60405173ffffffffffffffffffffffffffffffffffffffff8616907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a260608573ffffffffffffffffffffffffffffffffffffffff1688602001518a604051611c299190612d29565b60006040518083038185875af1925050503d8060008114611c66576040519150601f19603f3d011682016040523d82523d6000602084013e611c6b565b606091505b50909250905081611ccc577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed163115611dfe578673ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d8060008114611d98576040519150601f19603f3d011682016040523d82523d6000602084013e611d9d565b606091505b50909250905081611dfe577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b505050505095945050505050565b60006103dd611e8c60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b868686866116f1565b60006103dd85858585336116f1565b60006103dd611f2460408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b86868686611a17565b6000808360601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f092505073ffffffffffffffffffffffffffffffffffffffff8216612016576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b60405173ffffffffffffffffffffffffffffffffffffffff8316907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a26000808373ffffffffffffffffffffffffffffffffffffffff1634866040516120809190612d29565b60006040518083038185875af1925050503d80600081146120bd576040519150601f19603f3d011682016040523d82523d6000602084013e6120c2565b606091505b50915091506120d282828861247d565b50505092915050565b60008060006120e9846125b3565b9092509050600082600281111561210257612102612e02565b1480156121205750600081600281111561211e5761211e612e02565b145b1561215e57604080513360208201524691810191909152606081018590526080016040516020818303038152906040528051906020012092506123cc565b600082600281111561217257612172612e02565b1480156121905750600181600281111561218e5761218e612e02565b145b156121b0576121a9338560009182526020526040902090565b92506123cc565b60008260028111156121c4576121c4612e02565b03612233576040517f13b3a2a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b600182600281111561224757612247612e02565b1480156122655750600081600281111561226357612263612e02565b145b1561227e576121a9468560009182526020526040902090565b600182600281111561229257612292612e02565b1480156122b0575060028160028111156122ae576122ae612e02565b145b1561231f576040517f13b3a2a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b61239a60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b84036123a657836123c9565b604080516020810186905201604051602081830303815290604052805190602001205b92505b5050919050565b73ffffffffffffffffffffffffffffffffffffffff8116158061240b575073ffffffffffffffffffffffffffffffffffffffff81163b155b1561247a576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b50565b82158061249f575073ffffffffffffffffffffffffffffffffffffffff81163b155b156124fa577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed826040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b505050565b811580612520575073ffffffffffffffffffffffffffffffffffffffff8116155b80612540575073ffffffffffffffffffffffffffffffffffffffff81163b155b156125af576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b5050565b600080606083901c3314801561261057508260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000145b1561262057506000905080915091565b606083901c3314801561265a57507fff00000000000000000000000000000000000000000000000000000000000000601484901a60f81b16155b1561266b5750600090506001915091565b33606084901c036126825750600090506002915091565b606083901c1580156126db57508260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000145b156126ec5750600190506000915091565b606083901c15801561272557507fff00000000000000000000000000000000000000000000000000000000000000601484901a60f81b16155b1561273557506001905080915091565b606083901c61274a5750600190506002915091565b8260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000036127a55750600290506000915091565b8260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166000036127e15750600290506001915091565b506002905080915091565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261282c57600080fd5b813567ffffffffffffffff80821115612847576128476127ec565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561288d5761288d6127ec565b816040528381528660208588010111156128a657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000604082840312156128d857600080fd5b6040516040810181811067ffffffffffffffff821117156128fb576128fb6127ec565b604052823581526020928301359281019290925250919050565b60008060008060a0858703121561292b57600080fd5b84359350602085013567ffffffffffffffff8082111561294a57600080fd5b6129568883890161281b565b9450604087013591508082111561296c57600080fd5b506129798782880161281b565b92505061298986606087016128c6565b905092959194509250565b600080604083850312156129a757600080fd5b82359150602083013567ffffffffffffffff8111156129c557600080fd5b6129d18582860161281b565b9150509250929050565b6000602082840312156129ed57600080fd5b813567ffffffffffffffff811115612a0457600080fd5b6107b38482850161281b565b803573ffffffffffffffffffffffffffffffffffffffff81168114612a3457600080fd5b919050565b600080600060608486031215612a4e57600080fd5b83359250612a5e60208501612a10565b9150604084013567ffffffffffffffff811115612a7a57600080fd5b612a868682870161281b565b9150509250925092565b600060208284031215612aa257600080fd5b5035919050565b600080600060808486031215612abe57600080fd5b833567ffffffffffffffff80821115612ad657600080fd5b612ae28783880161281b565b94506020860135915080821115612af857600080fd5b50612b058682870161281b565b925050612b1585604086016128c6565b90509250925092565b60008060408385031215612b3157600080fd5b82359150612b4160208401612a10565b90509250929050565b60008060408385031215612b5d57600080fd5b612b6683612a10565b946020939093013593505050565b60008060408385031215612b8757600080fd5b612b9083612a10565b9150602083013567ffffffffffffffff8111156129c557600080fd5b60008060408385031215612bbf57600080fd5b50508035926020909101359150565b60008060008060a08587031215612be457600080fd5b843567ffffffffffffffff80821115612bfc57600080fd5b612c088883890161281b565b95506020870135915080821115612c1e57600080fd5b50612c2b8782880161281b565b935050612c3b86604087016128c6565b915061298960808601612a10565b600080600080600060c08688031215612c6157600080fd5b85359450602086013567ffffffffffffffff80821115612c8057600080fd5b612c8c89838a0161281b565b95506040880135915080821115612ca257600080fd5b50612caf8882890161281b565b935050612cbf87606088016128c6565b9150612ccd60a08701612a10565b90509295509295909350565b600080600060608486031215612cee57600080fd5b8335925060208401359150612b1560408501612a10565b60005b83811015612d20578181015183820152602001612d08565b50506000910152565b60008251612d3b818460208701612d05565b9190910192915050565b67ffffffffffffffff828116828216039080821115612d8d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260008251806040840152612dcf816060850160208701612d05565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000817000a
Verified Source Code Partial Match
Compiler: v0.8.23+commit.f704f362
EVM: paris
Optimization: Yes (10000000 runs)
CreateX.sol 1032 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.23;
/**
* @title CreateX Factory Smart Contract
* @author pcaversaccio (https://web.archive.org/web/20230921103111/https://pcaversaccio.com/)
* @custom:coauthor Matt Solomon (https://web.archive.org/web/20230921103335/https://mattsolomon.dev/)
* @notice Factory smart contract to make easier and safer usage of the
* `CREATE` (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f0?fork=shanghai) and `CREATE2`
* (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f5?fork=shanghai) EVM opcodes as well as of
* `CREATE3`-based (https://web.archive.org/web/20230921103920/https://github.com/ethereum/EIPs/pull/3171) contract creations.
* @dev To simplify testing of non-public variables and functions, we use the `internal`
* function visibility specifier `internal` for all variables and functions, even though
* they could technically be `private` since we do not expect anyone to inherit from
* the `CreateX` contract.
* @custom:security-contact See https://web.archive.org/web/20230921105029/https://raw.githubusercontent.com/pcaversaccio/createx/main/SECURITY.md.
*/
contract CreateX {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Caches the contract address at construction, to be used for the custom errors.
*/
address internal immutable _SELF = address(this);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TYPES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Struct for the `payable` amounts in a deploy-and-initialise call.
*/
struct Values {
uint256 constructorAmount;
uint256 initCallAmount;
}
/**
* @dev Enum for the selection of a permissioned deploy protection.
*/
enum SenderBytes {
MsgSender,
ZeroAddress,
Random
}
/**
* @dev Enum for the selection of a cross-chain redeploy protection.
*/
enum RedeployProtectionFlag {
True,
False,
Unspecified
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Event that is emitted when a contract is successfully created.
* @param newContract The address of the new contract.
* @param salt The 32-byte random value used to create the contract address.
*/
event ContractCreation(address indexed newContract, bytes32 indexed salt);
/**
* @dev Event that is emitted when a contract is successfully created.
* @param newContract The address of the new contract.
*/
event ContractCreation(address indexed newContract);
/**
* @dev Event that is emitted when a `CREATE3` proxy contract is successfully created.
* @param newContract The address of the new proxy contract.
* @param salt The 32-byte random value used to create the proxy address.
*/
event Create3ProxyContractCreation(address indexed newContract, bytes32 indexed salt);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Error that occurs when the contract creation failed.
* @param emitter The contract that emits the error.
*/
error FailedContractCreation(address emitter);
/**
* @dev Error that occurs when the contract initialisation call failed.
* @param emitter The contract that emits the error.
* @param revertData The data returned by the failed initialisation call.
*/
error FailedContractInitialisation(address emitter, bytes revertData);
/**
* @dev Error that occurs when the salt value is invalid.
* @param emitter The contract that emits the error.
*/
error InvalidSalt(address emitter);
/**
* @dev Error that occurs when the nonce value is invalid.
* @param emitter The contract that emits the error.
*/
error InvalidNonceValue(address emitter);
/**
* @dev Error that occurs when transferring ether has failed.
* @param emitter The contract that emits the error.
* @param revertData The data returned by the failed ether transfer.
*/
error FailedEtherTransfer(address emitter, bytes revertData);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via calling the `CREATE` opcode and using the creation
* bytecode `initCode` and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero,
* `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate(bytes memory initCode) public payable returns (address newContract) {
assembly ("memory-safe") {
newContract := create(callvalue(), add(initCode, 0x20), mload(initCode))
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. In order to
* save deployment costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount`
* is non-zero, `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateAndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
assembly ("memory-safe") {
newContract := create(mload(values), add(initCode, 0x20), mload(initCode))
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract});
(bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, and `msg.value` as inputs. In order to save deployment costs, we do not
* sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateAndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
newContract = deployCreateAndInit({initCode: initCode, data: data, values: values, refundAddress: msg.sender});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE` opcode, and initialises
* the implementation contract using the implementation address `implementation`, the initialisation
* code `data`, and `msg.value` as inputs. Note that if `msg.value` is non-zero, the initialiser
* function called via `data` must be `payable`.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateClone(address implementation, bytes memory data) public payable returns (address proxy) {
bytes20 implementationInBytes = bytes20(implementation);
assembly ("memory-safe") {
let clone := mload(0x40)
mstore(
clone,
hex"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00"
)
mstore(add(clone, 0x14), implementationInBytes)
mstore(
add(clone, 0x28),
hex"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00"
)
proxy := create(0, clone, 0x37)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit ContractCreation({newContract: proxy});
(bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);
_requireSuccessfulContractInitialisation({
success: success,
returnData: returnData,
implementation: implementation
});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP) encoding
* scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)
* and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
* For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.
*
* Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,
* all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the
* first contract address created by another contract is calculated with a non-zero nonce.
* @param deployer The 20-byte deployer address.
* @param nonce The next 32-byte nonce of the deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreateAddress(address deployer, uint256 nonce) public view returns (address computedAddress) {
bytes memory data;
bytes1 len = bytes1(0x94);
// The theoretical allowed limit, based on EIP-2681, for an account nonce is 2**64-2:
// https://web.archive.org/web/20230921113252/https://eips.ethereum.org/EIPS/eip-2681.
if (nonce > type(uint64).max - 1) {
revert InvalidNonceValue({emitter: _SELF});
}
// The integer zero is treated as an empty byte string and therefore has only one length prefix,
// 0x80, which is calculated via 0x80 + 0.
if (nonce == 0x00) {
data = abi.encodePacked(bytes1(0xd6), len, deployer, bytes1(0x80));
}
// A one-byte integer in the [0x00, 0x7f] range uses its own value as a length prefix, there is no
// additional "0x80 + length" prefix that precedes it.
else if (nonce <= 0x7f) {
data = abi.encodePacked(bytes1(0xd6), len, deployer, uint8(nonce));
}
// In the case of `nonce > 0x7f` and `nonce <= type(uint8).max`, we have the following encoding scheme
// (the same calculation can be carried over for higher nonce bytes):
// 0xda = 0xc0 (short RLP prefix) + 0x1a (= the bytes length of: 0x94 + address + 0x84 + nonce, in hex),
// 0x94 = 0x80 + 0x14 (= the bytes length of an address, 20 bytes, in hex),
// 0x84 = 0x80 + 0x04 (= the bytes length of the nonce, 4 bytes, in hex).
else if (nonce <= type(uint8).max) {
data = abi.encodePacked(bytes1(0xd7), len, deployer, bytes1(0x81), uint8(nonce));
} else if (nonce <= type(uint16).max) {
data = abi.encodePacked(bytes1(0xd8), len, deployer, bytes1(0x82), uint16(nonce));
} else if (nonce <= type(uint24).max) {
data = abi.encodePacked(bytes1(0xd9), len, deployer, bytes1(0x83), uint24(nonce));
} else if (nonce <= type(uint32).max) {
data = abi.encodePacked(bytes1(0xda), len, deployer, bytes1(0x84), uint32(nonce));
} else if (nonce <= type(uint40).max) {
data = abi.encodePacked(bytes1(0xdb), len, deployer, bytes1(0x85), uint40(nonce));
} else if (nonce <= type(uint48).max) {
data = abi.encodePacked(bytes1(0xdc), len, deployer, bytes1(0x86), uint48(nonce));
} else if (nonce <= type(uint56).max) {
data = abi.encodePacked(bytes1(0xdd), len, deployer, bytes1(0x87), uint56(nonce));
} else {
data = abi.encodePacked(bytes1(0xde), len, deployer, bytes1(0x88), uint64(nonce));
}
computedAddress = address(uint160(uint256(keccak256(data))));
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract
* using the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP)
* encoding scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)
* and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
* For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.
*
* Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,
* all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the
* first contract address created by another contract is calculated with a non-zero nonce.
* @param nonce The next 32-byte nonce of this contract.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreateAddress(uint256 nonce) public view returns (address computedAddress) {
computedAddress = computeCreateAddress({deployer: _SELF, nonce: nonce});
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE2 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via calling the `CREATE2` opcode and using the salt value `salt`,
* the creation bytecode `initCode`, and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero, `initCode`
* must have a `payable` constructor.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate2(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
assembly ("memory-safe") {
newContract := create2(callvalue(), add(initCode, 0x20), mload(initCode), guardedSalt)
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract, salt: guardedSalt});
}
/**
* @dev Deploys a new contract via calling the `CREATE2` opcode and using the creation bytecode
* `initCode` and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a
* diverse selection of block and transaction properties. This approach does not guarantee true
* randomness! In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate2(bytes memory initCode) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2`.
newContract = deployCreate2({salt: _generateSalt(), initCode: initCode});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* salt value `salt`, the creation bytecode `initCode`, the initialisation code `data`, the struct
* for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs.
* In order to save deployment costs, we do not sanity check the `initCode` length. Note that if
* `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
assembly ("memory-safe") {
newContract := create2(mload(values), add(initCode, 0x20), mload(initCode), guardedSalt)
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract, salt: guardedSalt});
(bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* salt value `salt`, creation bytecode `initCode`, the initialisation code `data`, the struct for
* the `payable` amounts `values`, and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: salt,
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. The salt value
* is calculated pseudo-randomly using a diverse selection of block and transaction properties.
* This approach does not guarantee true randomness! In order to save deployment costs, we do not
* sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode`
* must have a `payable` constructor.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: refundAddress
});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable` amounts
* `values`, and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a
* diverse selection of block and transaction properties. This approach does not guarantee true
* randomness! In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt
* value `salt`, and initialises the implementation contract using the implementation address
* `implementation`, the initialisation code `data`, and `msg.value` as inputs. Note that if
* `msg.value` is non-zero, the initialiser function called via `data` must be `payable`.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2Clone(
bytes32 salt,
address implementation,
bytes memory data
) public payable returns (address proxy) {
bytes32 guardedSalt = _guard({salt: salt});
bytes20 implementationInBytes = bytes20(implementation);
assembly ("memory-safe") {
let clone := mload(0x40)
mstore(
clone,
hex"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00"
)
mstore(add(clone, 0x14), implementationInBytes)
mstore(
add(clone, 0x28),
hex"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00"
)
proxy := create2(0, clone, 0x37, guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit ContractCreation({newContract: proxy, salt: guardedSalt});
(bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);
_requireSuccessfulContractInitialisation({
success: success,
returnData: returnData,
implementation: implementation
});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt
* value `salt`, and initialises the implementation contract using the implementation address
* `implementation`, the initialisation code `data`, and `msg.value` as inputs. The salt value is
* calculated pseudo-randomly using a diverse selection of block and transaction properties. This
* approach does not guarantee true randomness! Note that if `msg.value` is non-zero, the initialiser
* function called via `data` must be `payable`.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2Clone(address implementation, bytes memory data) public payable returns (address proxy) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2Clone`.
proxy = deployCreate2Clone({salt: _generateSalt(), implementation: implementation, data: data});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new
* destination address. This implementation is based on OpenZeppelin:
* https://web.archive.org/web/20230921113703/https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/181d518609a9f006fcb97af63e6952e603cf100e/contracts/utils/Create2.sol.
* @param salt The 32-byte random value used to create the contract address.
* @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.
* @param deployer The 20-byte deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate2Address(
bytes32 salt,
bytes32 initCodeHash,
address deployer
) public pure returns (address computedAddress) {
assembly ("memory-safe") {
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |----------------------|---------------------------------------------------------------------------|
// | initCodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |----------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak256(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
let ptr := mload(0x40)
mstore(add(ptr, 0x40), initCodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer)
let start := add(ptr, 0x0b)
mstore8(start, 0xff)
computedAddress := keccak256(start, 85)
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract using
* the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new
* destination address.
* @param salt The 32-byte random value used to create the contract address.
* @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) public view returns (address computedAddress) {
computedAddress = computeCreate2Address({salt: salt, initCodeHash: initCodeHash, deployer: _SELF});
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE3 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode
* factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`
* as inputs. In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor. This
* implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security We strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
bytes memory proxyChildBytecode = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
address proxy;
assembly ("memory-safe") {
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});
newContract = computeCreate3Address({salt: guardedSalt});
(bool success, ) = proxy.call{value: msg.value}(initCode);
_requireSuccessfulContractCreation({success: success, newContract: newContract});
emit ContractCreation({newContract: newContract});
}
/**
* @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode
* factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`
* as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block
* and transaction properties. This approach does not guarantee true randomness! In order to save
* deployment costs, we do not sanity check the `initCode` length. Note that if `msg.value` is
* non-zero, `initCode` must have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate3(bytes memory initCode) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3`.
newContract = deployCreate3({salt: _generateSalt(), initCode: initCode});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the
* initialisation code `data`, the struct for the `payable` amounts `values`, the refund address
* `refundAddress`, and `msg.value` as inputs. In order to save deployment costs, we do not sanity
* check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode` must
* have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
* Furthermore, we strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
bytes memory proxyChildBytecode = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
address proxy;
assembly ("memory-safe") {
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});
newContract = computeCreate3Address({salt: guardedSalt});
(bool success, ) = proxy.call{value: values.constructorAmount}(initCode);
_requireSuccessfulContractCreation({success: success, newContract: newContract});
emit ContractCreation({newContract: newContract});
bytes memory returnData;
(success, returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the
* initialisation code `data`, the struct for the `payable` amounts `values`, and `msg.value` as
* inputs. In order to save deployment costs, we do not sanity check the `initCode` length. Note
* that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
* Furthermore, we strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: salt,
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,
* the struct for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value`
* as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block and
* transaction properties. This approach does not guarantee true randomness! In order to save deployment
* costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate3AndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: refundAddress
});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,
* the struct for the `payable` amounts `values`, `msg.value` as inputs. The salt value is calculated
* pseudo-randomly using a diverse selection of block and transaction properties. This approach does
* not guarantee true randomness! In order to save deployment costs, we do not sanity check the `initCode`
* length. Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate3AndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will
* result in a new destination address. This implementation is based on Solady:
* https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param deployer The 20-byte deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate3Address(bytes32 salt, address deployer) public pure returns (address computedAddress) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(0x00, deployer)
mstore8(0x0b, 0xff)
mstore(0x20, salt)
mstore(
0x40,
hex"21_c3_5d_be_1b_34_4a_24_88_cf_33_21_d6_ce_54_2f_8e_9f_30_55_44_ff_09_e4_99_3a_62_31_9a_49_7c_1f"
)
mstore(0x14, keccak256(0x0b, 0x55))
mstore(0x40, ptr)
mstore(0x00, 0xd694)
mstore8(0x34, 0x01)
computedAddress := keccak256(0x1e, 0x17)
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract using
* the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will
* result in a new destination address. This implementation is based on Solady:
* https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate3Address(bytes32 salt) public view returns (address computedAddress) {
computedAddress = computeCreate3Address({salt: salt, deployer: _SELF});
}
/*´:°•.°+...
// [truncated — 59559 bytes total]
.sol 1032 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.23;
/**
* @title CreateX Factory Smart Contract
* @author pcaversaccio (https://web.archive.org/web/20230921103111/https://pcaversaccio.com/)
* @custom:coauthor Matt Solomon (https://web.archive.org/web/20230921103335/https://mattsolomon.dev/)
* @notice Factory smart contract to make easier and safer usage of the
* `CREATE` (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f0?fork=shanghai) and `CREATE2`
* (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f5?fork=shanghai) EVM opcodes as well as of
* `CREATE3`-based (https://web.archive.org/web/20230921103920/https://github.com/ethereum/EIPs/pull/3171) contract creations.
* @dev To simplify testing of non-public variables and functions, we use the `internal`
* function visibility specifier `internal` for all variables and functions, even though
* they could technically be `private` since we do not expect anyone to inherit from
* the `CreateX` contract.
* @custom:security-contact See https://web.archive.org/web/20230921105029/https://raw.githubusercontent.com/pcaversaccio/createx/main/SECURITY.md.
*/
contract CreateX {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Caches the contract address at construction, to be used for the custom errors.
*/
address internal immutable _SELF = address(this);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TYPES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Struct for the `payable` amounts in a deploy-and-initialise call.
*/
struct Values {
uint256 constructorAmount;
uint256 initCallAmount;
}
/**
* @dev Enum for the selection of a permissioned deploy protection.
*/
enum SenderBytes {
MsgSender,
ZeroAddress,
Random
}
/**
* @dev Enum for the selection of a cross-chain redeploy protection.
*/
enum RedeployProtectionFlag {
True,
False,
Unspecified
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Event that is emitted when a contract is successfully created.
* @param newContract The address of the new contract.
* @param salt The 32-byte random value used to create the contract address.
*/
event ContractCreation(address indexed newContract, bytes32 indexed salt);
/**
* @dev Event that is emitted when a contract is successfully created.
* @param newContract The address of the new contract.
*/
event ContractCreation(address indexed newContract);
/**
* @dev Event that is emitted when a `CREATE3` proxy contract is successfully created.
* @param newContract The address of the new proxy contract.
* @param salt The 32-byte random value used to create the proxy address.
*/
event Create3ProxyContractCreation(address indexed newContract, bytes32 indexed salt);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Error that occurs when the contract creation failed.
* @param emitter The contract that emits the error.
*/
error FailedContractCreation(address emitter);
/**
* @dev Error that occurs when the contract initialisation call failed.
* @param emitter The contract that emits the error.
* @param revertData The data returned by the failed initialisation call.
*/
error FailedContractInitialisation(address emitter, bytes revertData);
/**
* @dev Error that occurs when the salt value is invalid.
* @param emitter The contract that emits the error.
*/
error InvalidSalt(address emitter);
/**
* @dev Error that occurs when the nonce value is invalid.
* @param emitter The contract that emits the error.
*/
error InvalidNonceValue(address emitter);
/**
* @dev Error that occurs when transferring ether has failed.
* @param emitter The contract that emits the error.
* @param revertData The data returned by the failed ether transfer.
*/
error FailedEtherTransfer(address emitter, bytes revertData);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via calling the `CREATE` opcode and using the creation
* bytecode `initCode` and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero,
* `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate(bytes memory initCode) public payable returns (address newContract) {
assembly ("memory-safe") {
newContract := create(callvalue(), add(initCode, 0x20), mload(initCode))
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. In order to
* save deployment costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount`
* is non-zero, `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateAndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
assembly ("memory-safe") {
newContract := create(mload(values), add(initCode, 0x20), mload(initCode))
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract});
(bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, and `msg.value` as inputs. In order to save deployment costs, we do not
* sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateAndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
newContract = deployCreateAndInit({initCode: initCode, data: data, values: values, refundAddress: msg.sender});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE` opcode, and initialises
* the implementation contract using the implementation address `implementation`, the initialisation
* code `data`, and `msg.value` as inputs. Note that if `msg.value` is non-zero, the initialiser
* function called via `data` must be `payable`.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateClone(address implementation, bytes memory data) public payable returns (address proxy) {
bytes20 implementationInBytes = bytes20(implementation);
assembly ("memory-safe") {
let clone := mload(0x40)
mstore(
clone,
hex"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00"
)
mstore(add(clone, 0x14), implementationInBytes)
mstore(
add(clone, 0x28),
hex"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00"
)
proxy := create(0, clone, 0x37)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit ContractCreation({newContract: proxy});
(bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);
_requireSuccessfulContractInitialisation({
success: success,
returnData: returnData,
implementation: implementation
});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP) encoding
* scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)
* and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
* For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.
*
* Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,
* all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the
* first contract address created by another contract is calculated with a non-zero nonce.
* @param deployer The 20-byte deployer address.
* @param nonce The next 32-byte nonce of the deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreateAddress(address deployer, uint256 nonce) public view returns (address computedAddress) {
bytes memory data;
bytes1 len = bytes1(0x94);
// The theoretical allowed limit, based on EIP-2681, for an account nonce is 2**64-2:
// https://web.archive.org/web/20230921113252/https://eips.ethereum.org/EIPS/eip-2681.
if (nonce > type(uint64).max - 1) {
revert InvalidNonceValue({emitter: _SELF});
}
// The integer zero is treated as an empty byte string and therefore has only one length prefix,
// 0x80, which is calculated via 0x80 + 0.
if (nonce == 0x00) {
data = abi.encodePacked(bytes1(0xd6), len, deployer, bytes1(0x80));
}
// A one-byte integer in the [0x00, 0x7f] range uses its own value as a length prefix, there is no
// additional "0x80 + length" prefix that precedes it.
else if (nonce <= 0x7f) {
data = abi.encodePacked(bytes1(0xd6), len, deployer, uint8(nonce));
}
// In the case of `nonce > 0x7f` and `nonce <= type(uint8).max`, we have the following encoding scheme
// (the same calculation can be carried over for higher nonce bytes):
// 0xda = 0xc0 (short RLP prefix) + 0x1a (= the bytes length of: 0x94 + address + 0x84 + nonce, in hex),
// 0x94 = 0x80 + 0x14 (= the bytes length of an address, 20 bytes, in hex),
// 0x84 = 0x80 + 0x04 (= the bytes length of the nonce, 4 bytes, in hex).
else if (nonce <= type(uint8).max) {
data = abi.encodePacked(bytes1(0xd7), len, deployer, bytes1(0x81), uint8(nonce));
} else if (nonce <= type(uint16).max) {
data = abi.encodePacked(bytes1(0xd8), len, deployer, bytes1(0x82), uint16(nonce));
} else if (nonce <= type(uint24).max) {
data = abi.encodePacked(bytes1(0xd9), len, deployer, bytes1(0x83), uint24(nonce));
} else if (nonce <= type(uint32).max) {
data = abi.encodePacked(bytes1(0xda), len, deployer, bytes1(0x84), uint32(nonce));
} else if (nonce <= type(uint40).max) {
data = abi.encodePacked(bytes1(0xdb), len, deployer, bytes1(0x85), uint40(nonce));
} else if (nonce <= type(uint48).max) {
data = abi.encodePacked(bytes1(0xdc), len, deployer, bytes1(0x86), uint48(nonce));
} else if (nonce <= type(uint56).max) {
data = abi.encodePacked(bytes1(0xdd), len, deployer, bytes1(0x87), uint56(nonce));
} else {
data = abi.encodePacked(bytes1(0xde), len, deployer, bytes1(0x88), uint64(nonce));
}
computedAddress = address(uint160(uint256(keccak256(data))));
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract
* using the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP)
* encoding scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)
* and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
* For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.
*
* Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,
* all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the
* first contract address created by another contract is calculated with a non-zero nonce.
* @param nonce The next 32-byte nonce of this contract.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreateAddress(uint256 nonce) public view returns (address computedAddress) {
computedAddress = computeCreateAddress({deployer: _SELF, nonce: nonce});
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE2 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via calling the `CREATE2` opcode and using the salt value `salt`,
* the creation bytecode `initCode`, and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero, `initCode`
* must have a `payable` constructor.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate2(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
assembly ("memory-safe") {
newContract := create2(callvalue(), add(initCode, 0x20), mload(initCode), guardedSalt)
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract, salt: guardedSalt});
}
/**
* @dev Deploys a new contract via calling the `CREATE2` opcode and using the creation bytecode
* `initCode` and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a
* diverse selection of block and transaction properties. This approach does not guarantee true
* randomness! In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate2(bytes memory initCode) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2`.
newContract = deployCreate2({salt: _generateSalt(), initCode: initCode});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* salt value `salt`, the creation bytecode `initCode`, the initialisation code `data`, the struct
* for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs.
* In order to save deployment costs, we do not sanity check the `initCode` length. Note that if
* `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
assembly ("memory-safe") {
newContract := create2(mload(values), add(initCode, 0x20), mload(initCode), guardedSalt)
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract, salt: guardedSalt});
(bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* salt value `salt`, creation bytecode `initCode`, the initialisation code `data`, the struct for
* the `payable` amounts `values`, and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: salt,
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. The salt value
* is calculated pseudo-randomly using a diverse selection of block and transaction properties.
* This approach does not guarantee true randomness! In order to save deployment costs, we do not
* sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode`
* must have a `payable` constructor.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: refundAddress
});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable` amounts
* `values`, and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a
* diverse selection of block and transaction properties. This approach does not guarantee true
* randomness! In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt
* value `salt`, and initialises the implementation contract using the implementation address
* `implementation`, the initialisation code `data`, and `msg.value` as inputs. Note that if
* `msg.value` is non-zero, the initialiser function called via `data` must be `payable`.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2Clone(
bytes32 salt,
address implementation,
bytes memory data
) public payable returns (address proxy) {
bytes32 guardedSalt = _guard({salt: salt});
bytes20 implementationInBytes = bytes20(implementation);
assembly ("memory-safe") {
let clone := mload(0x40)
mstore(
clone,
hex"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00"
)
mstore(add(clone, 0x14), implementationInBytes)
mstore(
add(clone, 0x28),
hex"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00"
)
proxy := create2(0, clone, 0x37, guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit ContractCreation({newContract: proxy, salt: guardedSalt});
(bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);
_requireSuccessfulContractInitialisation({
success: success,
returnData: returnData,
implementation: implementation
});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt
* value `salt`, and initialises the implementation contract using the implementation address
* `implementation`, the initialisation code `data`, and `msg.value` as inputs. The salt value is
* calculated pseudo-randomly using a diverse selection of block and transaction properties. This
* approach does not guarantee true randomness! Note that if `msg.value` is non-zero, the initialiser
* function called via `data` must be `payable`.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2Clone(address implementation, bytes memory data) public payable returns (address proxy) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2Clone`.
proxy = deployCreate2Clone({salt: _generateSalt(), implementation: implementation, data: data});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new
* destination address. This implementation is based on OpenZeppelin:
* https://web.archive.org/web/20230921113703/https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/181d518609a9f006fcb97af63e6952e603cf100e/contracts/utils/Create2.sol.
* @param salt The 32-byte random value used to create the contract address.
* @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.
* @param deployer The 20-byte deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate2Address(
bytes32 salt,
bytes32 initCodeHash,
address deployer
) public pure returns (address computedAddress) {
assembly ("memory-safe") {
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |----------------------|---------------------------------------------------------------------------|
// | initCodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |----------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak256(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
let ptr := mload(0x40)
mstore(add(ptr, 0x40), initCodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer)
let start := add(ptr, 0x0b)
mstore8(start, 0xff)
computedAddress := keccak256(start, 85)
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract using
* the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new
* destination address.
* @param salt The 32-byte random value used to create the contract address.
* @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) public view returns (address computedAddress) {
computedAddress = computeCreate2Address({salt: salt, initCodeHash: initCodeHash, deployer: _SELF});
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE3 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode
* factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`
* as inputs. In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor. This
* implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security We strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
bytes memory proxyChildBytecode = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
address proxy;
assembly ("memory-safe") {
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});
newContract = computeCreate3Address({salt: guardedSalt});
(bool success, ) = proxy.call{value: msg.value}(initCode);
_requireSuccessfulContractCreation({success: success, newContract: newContract});
emit ContractCreation({newContract: newContract});
}
/**
* @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode
* factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`
* as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block
* and transaction properties. This approach does not guarantee true randomness! In order to save
* deployment costs, we do not sanity check the `initCode` length. Note that if `msg.value` is
* non-zero, `initCode` must have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate3(bytes memory initCode) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3`.
newContract = deployCreate3({salt: _generateSalt(), initCode: initCode});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the
* initialisation code `data`, the struct for the `payable` amounts `values`, the refund address
* `refundAddress`, and `msg.value` as inputs. In order to save deployment costs, we do not sanity
* check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode` must
* have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
* Furthermore, we strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
bytes memory proxyChildBytecode = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
address proxy;
assembly ("memory-safe") {
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});
newContract = computeCreate3Address({salt: guardedSalt});
(bool success, ) = proxy.call{value: values.constructorAmount}(initCode);
_requireSuccessfulContractCreation({success: success, newContract: newContract});
emit ContractCreation({newContract: newContract});
bytes memory returnData;
(success, returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the
* initialisation code `data`, the struct for the `payable` amounts `values`, and `msg.value` as
* inputs. In order to save deployment costs, we do not sanity check the `initCode` length. Note
* that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
* Furthermore, we strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: salt,
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,
* the struct for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value`
* as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block and
* transaction properties. This approach does not guarantee true randomness! In order to save deployment
* costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate3AndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: refundAddress
});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,
* the struct for the `payable` amounts `values`, `msg.value` as inputs. The salt value is calculated
* pseudo-randomly using a diverse selection of block and transaction properties. This approach does
* not guarantee true randomness! In order to save deployment costs, we do not sanity check the `initCode`
* length. Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate3AndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will
* result in a new destination address. This implementation is based on Solady:
* https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param deployer The 20-byte deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate3Address(bytes32 salt, address deployer) public pure returns (address computedAddress) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(0x00, deployer)
mstore8(0x0b, 0xff)
mstore(0x20, salt)
mstore(
0x40,
hex"21_c3_5d_be_1b_34_4a_24_88_cf_33_21_d6_ce_54_2f_8e_9f_30_55_44_ff_09_e4_99_3a_62_31_9a_49_7c_1f"
)
mstore(0x14, keccak256(0x0b, 0x55))
mstore(0x40, ptr)
mstore(0x00, 0xd694)
mstore8(0x34, 0x01)
computedAddress := keccak256(0x1e, 0x17)
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract using
* the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will
* result in a new destination address. This implementation is based on Solady:
* https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate3Address(bytes32 salt) public view returns (address computedAddress) {
computedAddress = computeCreate3Address({salt: salt, deployer: _SELF});
}
/*´:°•.°+...
// [truncated — 59558 bytes total]
CreateX.sol 1032 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.23;
/**
* @title CreateX Factory Smart Contract
* @author pcaversaccio (https://web.archive.org/web/20230921103111/https://pcaversaccio.com/)
* @custom:coauthor Matt Solomon (https://web.archive.org/web/20230921103335/https://mattsolomon.dev/)
* @notice Factory smart contract to make easier and safer usage of the
* `CREATE` (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f0?fork=shanghai) and `CREATE2`
* (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f5?fork=shanghai) EVM opcodes as well as of
* `CREATE3`-based (https://web.archive.org/web/20230921103920/https://github.com/ethereum/EIPs/pull/3171) contract creations.
* @dev To simplify testing of non-public variables and functions, we use the `internal`
* function visibility specifier `internal` for all variables and functions, even though
* they could technically be `private` since we do not expect anyone to inherit from
* the `CreateX` contract.
* @custom:security-contact See https://web.archive.org/web/20230921105029/https://raw.githubusercontent.com/pcaversaccio/createx/main/SECURITY.md.
*/
contract CreateX {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Caches the contract address at construction, to be used for the custom errors.
*/
address internal immutable _SELF = address(this);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TYPES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Struct for the `payable` amounts in a deploy-and-initialise call.
*/
struct Values {
uint256 constructorAmount;
uint256 initCallAmount;
}
/**
* @dev Enum for the selection of a permissioned deploy protection.
*/
enum SenderBytes {
MsgSender,
ZeroAddress,
Random
}
/**
* @dev Enum for the selection of a cross-chain redeploy protection.
*/
enum RedeployProtectionFlag {
True,
False,
Unspecified
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Event that is emitted when a contract is successfully created.
* @param newContract The address of the new contract.
* @param salt The 32-byte random value used to create the contract address.
*/
event ContractCreation(address indexed newContract, bytes32 indexed salt);
/**
* @dev Event that is emitted when a contract is successfully created.
* @param newContract The address of the new contract.
*/
event ContractCreation(address indexed newContract);
/**
* @dev Event that is emitted when a `CREATE3` proxy contract is successfully created.
* @param newContract The address of the new proxy contract.
* @param salt The 32-byte random value used to create the proxy address.
*/
event Create3ProxyContractCreation(address indexed newContract, bytes32 indexed salt);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Error that occurs when the contract creation failed.
* @param emitter The contract that emits the error.
*/
error FailedContractCreation(address emitter);
/**
* @dev Error that occurs when the contract initialisation call failed.
* @param emitter The contract that emits the error.
* @param revertData The data returned by the failed initialisation call.
*/
error FailedContractInitialisation(address emitter, bytes revertData);
/**
* @dev Error that occurs when the salt value is invalid.
* @param emitter The contract that emits the error.
*/
error InvalidSalt(address emitter);
/**
* @dev Error that occurs when the nonce value is invalid.
* @param emitter The contract that emits the error.
*/
error InvalidNonceValue(address emitter);
/**
* @dev Error that occurs when transferring ether has failed.
* @param emitter The contract that emits the error.
* @param revertData The data returned by the failed ether transfer.
*/
error FailedEtherTransfer(address emitter, bytes revertData);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via calling the `CREATE` opcode and using the creation
* bytecode `initCode` and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero,
* `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate(bytes memory initCode) public payable returns (address newContract) {
assembly ("memory-safe") {
newContract := create(callvalue(), add(initCode, 0x20), mload(initCode))
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. In order to
* save deployment costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount`
* is non-zero, `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateAndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
assembly ("memory-safe") {
newContract := create(mload(values), add(initCode, 0x20), mload(initCode))
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract});
(bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, and `msg.value` as inputs. In order to save deployment costs, we do not
* sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateAndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
newContract = deployCreateAndInit({initCode: initCode, data: data, values: values, refundAddress: msg.sender});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE` opcode, and initialises
* the implementation contract using the implementation address `implementation`, the initialisation
* code `data`, and `msg.value` as inputs. Note that if `msg.value` is non-zero, the initialiser
* function called via `data` must be `payable`.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreateClone(address implementation, bytes memory data) public payable returns (address proxy) {
bytes20 implementationInBytes = bytes20(implementation);
assembly ("memory-safe") {
let clone := mload(0x40)
mstore(
clone,
hex"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00"
)
mstore(add(clone, 0x14), implementationInBytes)
mstore(
add(clone, 0x28),
hex"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00"
)
proxy := create(0, clone, 0x37)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit ContractCreation({newContract: proxy});
(bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);
_requireSuccessfulContractInitialisation({
success: success,
returnData: returnData,
implementation: implementation
});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP) encoding
* scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)
* and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
* For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.
*
* Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,
* all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the
* first contract address created by another contract is calculated with a non-zero nonce.
* @param deployer The 20-byte deployer address.
* @param nonce The next 32-byte nonce of the deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreateAddress(address deployer, uint256 nonce) public view returns (address computedAddress) {
bytes memory data;
bytes1 len = bytes1(0x94);
// The theoretical allowed limit, based on EIP-2681, for an account nonce is 2**64-2:
// https://web.archive.org/web/20230921113252/https://eips.ethereum.org/EIPS/eip-2681.
if (nonce > type(uint64).max - 1) {
revert InvalidNonceValue({emitter: _SELF});
}
// The integer zero is treated as an empty byte string and therefore has only one length prefix,
// 0x80, which is calculated via 0x80 + 0.
if (nonce == 0x00) {
data = abi.encodePacked(bytes1(0xd6), len, deployer, bytes1(0x80));
}
// A one-byte integer in the [0x00, 0x7f] range uses its own value as a length prefix, there is no
// additional "0x80 + length" prefix that precedes it.
else if (nonce <= 0x7f) {
data = abi.encodePacked(bytes1(0xd6), len, deployer, uint8(nonce));
}
// In the case of `nonce > 0x7f` and `nonce <= type(uint8).max`, we have the following encoding scheme
// (the same calculation can be carried over for higher nonce bytes):
// 0xda = 0xc0 (short RLP prefix) + 0x1a (= the bytes length of: 0x94 + address + 0x84 + nonce, in hex),
// 0x94 = 0x80 + 0x14 (= the bytes length of an address, 20 bytes, in hex),
// 0x84 = 0x80 + 0x04 (= the bytes length of the nonce, 4 bytes, in hex).
else if (nonce <= type(uint8).max) {
data = abi.encodePacked(bytes1(0xd7), len, deployer, bytes1(0x81), uint8(nonce));
} else if (nonce <= type(uint16).max) {
data = abi.encodePacked(bytes1(0xd8), len, deployer, bytes1(0x82), uint16(nonce));
} else if (nonce <= type(uint24).max) {
data = abi.encodePacked(bytes1(0xd9), len, deployer, bytes1(0x83), uint24(nonce));
} else if (nonce <= type(uint32).max) {
data = abi.encodePacked(bytes1(0xda), len, deployer, bytes1(0x84), uint32(nonce));
} else if (nonce <= type(uint40).max) {
data = abi.encodePacked(bytes1(0xdb), len, deployer, bytes1(0x85), uint40(nonce));
} else if (nonce <= type(uint48).max) {
data = abi.encodePacked(bytes1(0xdc), len, deployer, bytes1(0x86), uint48(nonce));
} else if (nonce <= type(uint56).max) {
data = abi.encodePacked(bytes1(0xdd), len, deployer, bytes1(0x87), uint56(nonce));
} else {
data = abi.encodePacked(bytes1(0xde), len, deployer, bytes1(0x88), uint64(nonce));
}
computedAddress = address(uint160(uint256(keccak256(data))));
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract
* using the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP)
* encoding scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)
* and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
* For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.
*
* Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,
* all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the
* first contract address created by another contract is calculated with a non-zero nonce.
* @param nonce The next 32-byte nonce of this contract.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreateAddress(uint256 nonce) public view returns (address computedAddress) {
computedAddress = computeCreateAddress({deployer: _SELF, nonce: nonce});
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE2 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via calling the `CREATE2` opcode and using the salt value `salt`,
* the creation bytecode `initCode`, and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero, `initCode`
* must have a `payable` constructor.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate2(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
assembly ("memory-safe") {
newContract := create2(callvalue(), add(initCode, 0x20), mload(initCode), guardedSalt)
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract, salt: guardedSalt});
}
/**
* @dev Deploys a new contract via calling the `CREATE2` opcode and using the creation bytecode
* `initCode` and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a
* diverse selection of block and transaction properties. This approach does not guarantee true
* randomness! In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate2(bytes memory initCode) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2`.
newContract = deployCreate2({salt: _generateSalt(), initCode: initCode});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* salt value `salt`, the creation bytecode `initCode`, the initialisation code `data`, the struct
* for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs.
* In order to save deployment costs, we do not sanity check the `initCode` length. Note that if
* `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
assembly ("memory-safe") {
newContract := create2(mload(values), add(initCode, 0x20), mload(initCode), guardedSalt)
}
_requireSuccessfulContractCreation({newContract: newContract});
emit ContractCreation({newContract: newContract, salt: guardedSalt});
(bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* salt value `salt`, creation bytecode `initCode`, the initialisation code `data`, the struct for
* the `payable` amounts `values`, and `msg.value` as inputs. In order to save deployment costs,
* we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.
* @param salt The 32-byte random value used to create the contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: salt,
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`
* amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. The salt value
* is calculated pseudo-randomly using a diverse selection of block and transaction properties.
* This approach does not guarantee true randomness! In order to save deployment costs, we do not
* sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode`
* must have a `payable` constructor.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: refundAddress
});
}
/**
* @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the
* creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable` amounts
* `values`, and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a
* diverse selection of block and transaction properties. This approach does not guarantee true
* randomness! In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2AndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2AndInit`.
newContract = deployCreate2AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt
* value `salt`, and initialises the implementation contract using the implementation address
* `implementation`, the initialisation code `data`, and `msg.value` as inputs. Note that if
* `msg.value` is non-zero, the initialiser function called via `data` must be `payable`.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2Clone(
bytes32 salt,
address implementation,
bytes memory data
) public payable returns (address proxy) {
bytes32 guardedSalt = _guard({salt: salt});
bytes20 implementationInBytes = bytes20(implementation);
assembly ("memory-safe") {
let clone := mload(0x40)
mstore(
clone,
hex"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00"
)
mstore(add(clone, 0x14), implementationInBytes)
mstore(
add(clone, 0x28),
hex"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00"
)
proxy := create2(0, clone, 0x37, guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit ContractCreation({newContract: proxy, salt: guardedSalt});
(bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);
_requireSuccessfulContractInitialisation({
success: success,
returnData: returnData,
implementation: implementation
});
}
/**
* @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt
* value `salt`, and initialises the implementation contract using the implementation address
* `implementation`, the initialisation code `data`, and `msg.value` as inputs. The salt value is
* calculated pseudo-randomly using a diverse selection of block and transaction properties. This
* approach does not guarantee true randomness! Note that if `msg.value` is non-zero, the initialiser
* function called via `data` must be `payable`.
* @param implementation The 20-byte implementation contract address.
* @param data The initialisation code that is passed to the deployed proxy contract.
* @return proxy The 20-byte address where the clone was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate2Clone(address implementation, bytes memory data) public payable returns (address proxy) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate2Clone`.
proxy = deployCreate2Clone({salt: _generateSalt(), implementation: implementation, data: data});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new
* destination address. This implementation is based on OpenZeppelin:
* https://web.archive.org/web/20230921113703/https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/181d518609a9f006fcb97af63e6952e603cf100e/contracts/utils/Create2.sol.
* @param salt The 32-byte random value used to create the contract address.
* @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.
* @param deployer The 20-byte deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate2Address(
bytes32 salt,
bytes32 initCodeHash,
address deployer
) public pure returns (address computedAddress) {
assembly ("memory-safe") {
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |----------------------|---------------------------------------------------------------------------|
// | initCodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |----------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak256(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
let ptr := mload(0x40)
mstore(add(ptr, 0x40), initCodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer)
let start := add(ptr, 0x0b)
mstore8(start, 0xff)
computedAddress := keccak256(start, 85)
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract using
* the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new
* destination address.
* @param salt The 32-byte random value used to create the contract address.
* @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) public view returns (address computedAddress) {
computedAddress = computeCreate2Address({salt: salt, initCodeHash: initCodeHash, deployer: _SELF});
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE3 */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode
* factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`
* as inputs. In order to save deployment costs, we do not sanity check the `initCode` length.
* Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor. This
* implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security We strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
bytes memory proxyChildBytecode = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
address proxy;
assembly ("memory-safe") {
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});
newContract = computeCreate3Address({salt: guardedSalt});
(bool success, ) = proxy.call{value: msg.value}(initCode);
_requireSuccessfulContractCreation({success: success, newContract: newContract});
emit ContractCreation({newContract: newContract});
}
/**
* @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode
* factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`
* as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block
* and transaction properties. This approach does not guarantee true randomness! In order to save
* deployment costs, we do not sanity check the `initCode` length. Note that if `msg.value` is
* non-zero, `initCode` must have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @return newContract The 20-byte address where the contract was deployed.
*/
function deployCreate3(bytes memory initCode) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3`.
newContract = deployCreate3({salt: _generateSalt(), initCode: initCode});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the
* initialisation code `data`, the struct for the `payable` amounts `values`, the refund address
* `refundAddress`, and `msg.value` as inputs. In order to save deployment costs, we do not sanity
* check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode` must
* have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
* Furthermore, we strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
bytes32 guardedSalt = _guard({salt: salt});
bytes memory proxyChildBytecode = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
address proxy;
assembly ("memory-safe") {
proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)
}
if (proxy == address(0)) {
revert FailedContractCreation({emitter: _SELF});
}
emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});
newContract = computeCreate3Address({salt: guardedSalt});
(bool success, ) = proxy.call{value: values.constructorAmount}(initCode);
_requireSuccessfulContractCreation({success: success, newContract: newContract});
emit ContractCreation({newContract: newContract});
bytes memory returnData;
(success, returnData) = newContract.call{value: values.initCallAmount}(data);
if (!success) {
revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});
}
if (_SELF.balance != 0) {
// Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`
// opcode) will be part of the refund transaction.
(success, returnData) = refundAddress.call{value: _SELF.balance}("");
if (!success) {
revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});
}
}
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the
* initialisation code `data`, the struct for the `payable` amounts `values`, and `msg.value` as
* inputs. In order to save deployment costs, we do not sanity check the `initCode` length. Note
* that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
* Furthermore, we strongly recommend implementing a permissioned deploy protection by setting
* the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun
* proxy deployments on other chains.
*/
function deployCreate3AndInit(
bytes32 salt,
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: salt,
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,
* the struct for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value`
* as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block and
* transaction properties. This approach does not guarantee true randomness! In order to save deployment
* costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,
* `initCode` must have a `payable` constructor. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @param refundAddress The 20-byte address where any excess ether is returned to.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate3AndInit(
bytes memory initCode,
bytes memory data,
Values memory values,
address refundAddress
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: refundAddress
});
}
/**
* @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without
* an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,
* the struct for the `payable` amounts `values`, `msg.value` as inputs. The salt value is calculated
* pseudo-randomly using a diverse selection of block and transaction properties. This approach does
* not guarantee true randomness! In order to save deployment costs, we do not sanity check the `initCode`
* length. Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,
* and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:
* https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.
* @param initCode The creation bytecode.
* @param data The initialisation code that is passed to the deployed contract.
* @param values The specific `payable` amounts for the deployment and initialisation call.
* @return newContract The 20-byte address where the contract was deployed.
* @custom:security This function allows for reentrancy, however we refrain from adding
* a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol
* level that potentially malicious reentrant calls do not affect your smart contract system.
*/
function deployCreate3AndInit(
bytes memory initCode,
bytes memory data,
Values memory values
) public payable returns (address newContract) {
// Note that the safeguarding function `_guard` is called as part of the overloaded function
// `deployCreate3AndInit`.
newContract = deployCreate3AndInit({
salt: _generateSalt(),
initCode: initCode,
data: data,
values: values,
refundAddress: msg.sender
});
}
/**
* @dev Returns the address where a contract will be stored if deployed via `deployer` using
* the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will
* result in a new destination address. This implementation is based on Solady:
* https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @param deployer The 20-byte deployer address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate3Address(bytes32 salt, address deployer) public pure returns (address computedAddress) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(0x00, deployer)
mstore8(0x0b, 0xff)
mstore(0x20, salt)
mstore(
0x40,
hex"21_c3_5d_be_1b_34_4a_24_88_cf_33_21_d6_ce_54_2f_8e_9f_30_55_44_ff_09_e4_99_3a_62_31_9a_49_7c_1f"
)
mstore(0x14, keccak256(0x0b, 0x55))
mstore(0x40, ptr)
mstore(0x00, 0xd694)
mstore8(0x34, 0x01)
computedAddress := keccak256(0x1e, 0x17)
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via this contract using
* the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will
* result in a new destination address. This implementation is based on Solady:
* https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.
* @param salt The 32-byte random value used to create the proxy contract address.
* @return computedAddress The 20-byte address where a contract will be stored.
*/
function computeCreate3Address(bytes32 salt) public view returns (address computedAddress) {
computedAddress = computeCreate3Address({salt: salt, deployer: _SELF});
}
/*´:°•.°+...
// [truncated — 59559 bytes total]
Read Contract
computeCreate2Address 0x890c283b → address
computeCreate2Address 0xd323826a → address
computeCreate3Address 0x42d654fc → address
computeCreate3Address 0x6cec2536 → address
computeCreateAddress 0x28ddd046 → address
computeCreateAddress 0x74637a7a → address
Write Contract 18 functions
These functions modify contract state and require a wallet transaction to execute.
deployCreate 0x27fe1822
bytes initCode
returns: address
deployCreate2 0x26307668
bytes32 salt
bytes initCode
returns: address
deployCreate2 0x26a32fc7
bytes initCode
returns: address
deployCreate2AndInit 0xd42dbb23
bytes32 salt
bytes initCode
bytes data
tuple values
address refundAddress
returns: address
deployCreate2AndInit 0x5040414d
bytes initCode
bytes data
tuple values
returns: address
deployCreate2AndInit 0xe32d1a31
bytes initCode
bytes data
tuple values
address refundAddress
returns: address
deployCreate2AndInit 0xd5dbdb36
bytes32 salt
bytes initCode
bytes data
tuple values
returns: address
deployCreate2Clone 0x2852527a
bytes32 salt
address implementation
bytes data
returns: address
deployCreate2Clone 0x81503da1
address implementation
bytes data
returns: address
deployCreate3 0x7f565360
bytes initCode
returns: address
deployCreate3 0x9c36a286
bytes32 salt
bytes initCode
returns: address
deployCreate3AndInit 0x151a82b9
bytes32 salt
bytes initCode
bytes data
tuple values
returns: address
deployCreate3AndInit 0x4505d462
bytes initCode
bytes data
tuple values
returns: address
deployCreate3AndInit 0x426e8c86
bytes32 salt
bytes initCode
bytes data
tuple values
address refundAddress
returns: address
deployCreate3AndInit 0x1ca643e0
bytes initCode
bytes data
tuple values
address refundAddress
returns: address
deployCreateAndInit 0x7f45be51
bytes initCode
bytes data
tuple values
returns: address
deployCreateAndInit 0x77134a95
bytes initCode
bytes data
tuple values
address refundAddress
returns: address
deployCreateClone 0xf9664498
address implementation
bytes data
returns: address
Recent Transactions
No transactions found for this address