From 3177f63a176f92a32f3d34b2f792ae37143a54e5 Mon Sep 17 00:00:00 2001 From: Mike Seiler Date: Wed, 8 Feb 2023 20:26:55 +0000 Subject: [PATCH] add test for transparent delegate proxy from openzeppelin --- .../contracts/TransparentUpgradeableProxy.hex | 1 + .../contracts/TransparentUpgradeableProxy.sol | 590 ++++++++++++++++++ itests/contracts/compile.sh | 6 +- itests/fevm_test.go | 12 + 4 files changed, 608 insertions(+), 1 deletion(-) create mode 100644 itests/contracts/TransparentUpgradeableProxy.hex create mode 100644 itests/contracts/TransparentUpgradeableProxy.sol diff --git a/itests/contracts/TransparentUpgradeableProxy.hex b/itests/contracts/TransparentUpgradeableProxy.hex new file mode 100644 index 000000000..d3430beee --- /dev/null +++ b/itests/contracts/TransparentUpgradeableProxy.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061256c806100206000396000f3fe60806040523480156200001157600080fd5b50600436106200003a5760003560e01c806320965255146200003f578063f8a8fd6d1462000061575b600080fd5b620000496200006d565b604051620000589190620002a6565b60405180910390f35b6200006b62000234565b005b6000806040516200007e9062000253565b604051809103906000f0801580156200009b573d6000803e3d6000fd5b509050600081604051620000af9062000261565b620000bb919062000308565b604051809103906000f080158015620000d8573d6000803e3d6000fd5b5090506000604051620000eb906200026f565b604051809103906000f08015801562000108573d6000803e3d6000fd5b5090508173ffffffffffffffffffffffffffffffffffffffff16633659cfe6826040518263ffffffff1660e01b815260040162000146919062000308565b600060405180830381600087803b1580156200016157600080fd5b505af115801562000176573d6000803e3d6000fd5b5050505060006040516200018a906200027d565b604051809103906000f080158015620001a7573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff16633ccc0522846040518263ffffffff1660e01b8152600401620001e5919062000308565b6020604051808303816000875af115801562000205573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022b91906200035b565b94505050505090565b6200023e6200006d565b6000146200025157620002506200038d565b5b565b6103f780620003bd83390190565b61174480620007b483390190565b6103ef8062001ef883390190565b61025080620022e783390190565b6000819050919050565b620002a0816200028b565b82525050565b6000602082019050620002bd600083018462000295565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620002f082620002c3565b9050919050565b6200030281620002e3565b82525050565b60006020820190506200031f6000830184620002f7565b92915050565b600080fd5b62000335816200028b565b81146200034157600080fd5b50565b60008151905062000355816200032a565b92915050565b60006020828403121562000374576200037362000325565b5b6000620003848482850162000344565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfe608060405234801561001057600080fd5b506103d7806100206000396000f3fe608060405234801561001057600080fd5b50600436106100455760003560e01c8063209652551461004e578063552410771461006c5780638129fc1c1461008857610046565b5b600180819055005b610056610092565b6040516100639190610218565b60405180910390f35b61008660048036038101906100819190610264565b61009c565b005b6100906100a6565b005b6000600154905090565b8060018190555050565b60008060019054906101000a900460ff161590508080156100d75750600160008054906101000a900460ff1660ff16105b8061010457506100e6306101dc565b1580156101035750600160008054906101000a900460ff1660ff16145b5b610143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013a90610314565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015610180576001600060016101000a81548160ff0219169083151502179055505b80156101d95760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516101d09190610386565b60405180910390a15b50565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000819050919050565b610212816101ff565b82525050565b600060208201905061022d6000830184610209565b92915050565b600080fd5b610241816101ff565b811461024c57600080fd5b50565b60008135905061025e81610238565b92915050565b60006020828403121561027a57610279610233565b5b60006102888482850161024f565b91505092915050565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b60006102fe602e83610291565b9150610309826102a2565b604082019050919050565b6000602082019050818103600083015261032d816102f1565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b600061037061036b61036684610334565b61034b565b61033e565b9050919050565b61038081610355565b82525050565b600060208201905061039b6000830184610377565b9291505056fea2646970667358221220934a8ba055f2e0df7da7dde7999f38a4972809a218a2a064683da10ad547f1fd64736f6c63430008110033608060405260405162001744380380620017448339818101604052810190620000299190620005c7565b80604051806020016040528060008152506200004e828260006200006860201b60201c565b50506200006133620000ab60201b60201c565b50620008fd565b62000079836200010960201b60201c565b600082511180620000875750805b15620000a657620000a483836200016060201b620003361760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000dc6200019660201b60201c565b82604051620000ed9291906200060a565b60405180910390a16200010681620001fa60201b60201c565b50565b6200011a81620002ea60201b60201c565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b60606200018e83836040518060600160405280602781526020016200171d60279139620003c060201b60201c565b905092915050565b6000620001d17fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b6200045260201b620003631760201c565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200026c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200026390620006be565b60405180910390fd5b80620002a67fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b6200045260201b620003631760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b62000300816200045c60201b6200036d1760201c565b62000342576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003399062000756565b60405180910390fd5b806200037c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200045260201b620003631760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051620003ec9190620007f1565b600060405180830381855af49150503d806000811462000429576040519150601f19603f3d011682016040523d82523d6000602084013e6200042e565b606091505b509150915062000447868383876200047f60201b60201c565b925050509392505050565b6000819050919050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315620004ef576000835103620004e657620004a3856200045c60201b60201c565b620004e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004dc906200085a565b60405180910390fd5b5b82905062000502565b6200050183836200050a60201b60201c565b5b949350505050565b6000825111156200051e5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005549190620008d9565b60405180910390fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200058f8262000562565b9050919050565b620005a18162000582565b8114620005ad57600080fd5b50565b600081519050620005c18162000596565b92915050565b600060208284031215620005e057620005df6200055d565b5b6000620005f084828501620005b0565b91505092915050565b620006048162000582565b82525050565b6000604082019050620006216000830185620005f9565b620006306020830184620005f9565b9392505050565b600082825260208201905092915050565b7f455243313936373a206e65772061646d696e20697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000620006a660268362000637565b9150620006b38262000648565b604082019050919050565b60006020820190508181036000830152620006d98162000697565b9050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b60006200073e602d8362000637565b91506200074b82620006e0565b604082019050919050565b6000602082019050818103600083015262000771816200072f565b9050919050565b600081519050919050565b600081905092915050565b60005b83811015620007ae57808201518184015260208101905062000791565b60008484015250505050565b6000620007c78262000778565b620007d3818562000783565b9350620007e58185602086016200078e565b80840191505092915050565b6000620007ff8284620007ba565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600062000842601d8362000637565b91506200084f826200080a565b602082019050919050565b60006020820190508181036000830152620008758162000833565b9050919050565b600081519050919050565b6000601f19601f8301169050919050565b6000620008a5826200087c565b620008b1818562000637565b9350620008c38185602086016200078e565b620008ce8162000887565b840191505092915050565b60006020820190508181036000830152620008f5818462000898565b905092915050565b610e10806200090d6000396000f3fe60806040526004361061004e5760003560e01c80633659cfe6146100675780634f1ef286146100835780635c60da1b1461009f5780638f283970146100bd578063f851a440146100d95761005d565b3661005d5761005b6100f7565b005b6100656100f7565b005b610081600480360381019061007c9190610916565b610111565b005b61009d600480360381019061009891906109a8565b61017f565b005b6100a761021c565b6040516100b49190610a17565b60405180910390f35b6100d760048036038101906100d29190610916565b61027b565b005b6100e16102d7565b6040516100ee9190610a17565b60405180910390f35b6100ff610390565b61010f61010a61040f565b61041e565b565b610119610444565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16036101735761015361049b565b61016e816040518060200160405280600081525060006104aa565b61017c565b61017b6100f7565b5b50565b610187610444565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff160361020e576102098383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060016104aa565b610217565b6102166100f7565b5b505050565b6000610226610444565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff160361026f5761026061049b565b61026861040f565b9050610278565b6102776100f7565b5b90565b610283610444565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16036102cb576102bd61049b565b6102c6816104d6565b6102d4565b6102d36100f7565b5b50565b60006102e1610444565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff160361032a5761031b61049b565b610323610444565b9050610333565b6103326100f7565b5b90565b606061035b8383604051806060016040528060278152602001610db460279139610522565b905092915050565b6000819050919050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b610398610444565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603610405576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103fc90610adb565b60405180910390fd5b61040d6105a8565b565b60006104196105aa565b905090565b3660008037600080366000845af43d6000803e806000811461043f573d6000f35b3d6000fd5b60006104727fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b610363565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600034146104a857600080fd5b565b6104b383610601565b6000825111806104c05750805b156104d1576104cf8383610336565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104ff610444565b8260405161050e929190610afb565b60405180910390a161051f81610650565b50565b60606000808573ffffffffffffffffffffffffffffffffffffffff168560405161054c9190610b95565b600060405180830381855af49150503d8060008114610587576040519150601f19603f3d011682016040523d82523d6000602084013e61058c565b606091505b509150915061059d86838387610730565b925050509392505050565b565b60006105d87f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b610363565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61060a816107a5565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036106bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b690610c1e565b60405180910390fd5b806106ec7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b610363565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060831561079257600083510361078a5761074a8561036d565b610789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078090610c8a565b60405180910390fd5b5b82905061079d565b61079c838361085e565b5b949350505050565b6107ae8161036d565b6107ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107e490610d1c565b60405180910390fd5b8061081a7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b610363565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000825111156108715781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a59190610d91565b60405180910390fd5b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006108e3826108b8565b9050919050565b6108f3816108d8565b81146108fe57600080fd5b50565b600081359050610910816108ea565b92915050565b60006020828403121561092c5761092b6108ae565b5b600061093a84828501610901565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261096857610967610943565b5b8235905067ffffffffffffffff81111561098557610984610948565b5b6020830191508360018202830111156109a1576109a061094d565b5b9250929050565b6000806000604084860312156109c1576109c06108ae565b5b60006109cf86828701610901565b935050602084013567ffffffffffffffff8111156109f0576109ef6108b3565b5b6109fc86828701610952565b92509250509250925092565b610a11816108d8565b82525050565b6000602082019050610a2c6000830184610a08565b92915050565b600082825260208201905092915050565b7f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60008201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760208201527f6574000000000000000000000000000000000000000000000000000000000000604082015250565b6000610ac5604283610a32565b9150610ad082610a43565b606082019050919050565b60006020820190508181036000830152610af481610ab8565b9050919050565b6000604082019050610b106000830185610a08565b610b1d6020830184610a08565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610b58578082015181840152602081019050610b3d565b60008484015250505050565b6000610b6f82610b24565b610b798185610b2f565b9350610b89818560208601610b3a565b80840191505092915050565b6000610ba18284610b64565b915081905092915050565b7f455243313936373a206e65772061646d696e20697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000610c08602683610a32565b9150610c1382610bac565b604082019050919050565b60006020820190508181036000830152610c3781610bfb565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000610c74601d83610a32565b9150610c7f82610c3e565b602082019050919050565b60006020820190508181036000830152610ca381610c67565b9050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b6000610d06602d83610a32565b9150610d1182610caa565b604082019050919050565b60006020820190508181036000830152610d3581610cf9565b9050919050565b600081519050919050565b6000601f19601f8301169050919050565b6000610d6382610d3c565b610d6d8185610a32565b9350610d7d818560208601610b3a565b610d8681610d47565b840191505092915050565b60006020820190508181036000830152610dab8184610d58565b90509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e09e1af8aa595ace2cac727dfa78b8a1c201fdfb2f2b3364541017dec279304b64736f6c63430008110033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564608060405234801561001057600080fd5b506103cf806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063209652551461004657806355241077146100645780638129fc1c14610080575b600080fd5b61004e61008a565b60405161005b9190610210565b60405180910390f35b61007e6004803603810190610079919061025c565b610094565b005b61008861009e565b005b6000600154905090565b8060018190555050565b60008060019054906101000a900460ff161590508080156100cf5750600160008054906101000a900460ff1660ff16105b806100fc57506100de306101d4565b1580156100fb5750600160008054906101000a900460ff1660ff16145b5b61013b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101329061030c565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015610178576001600060016101000a81548160ff0219169083151502179055505b80156101d15760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516101c8919061037e565b60405180910390a15b50565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000819050919050565b61020a816101f7565b82525050565b60006020820190506102256000830184610201565b92915050565b600080fd5b610239816101f7565b811461024457600080fd5b50565b60008135905061025681610230565b92915050565b6000602082840312156102725761027161022b565b5b600061028084828501610247565b91505092915050565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b60006102f6602e83610289565b91506103018261029a565b604082019050919050565b60006020820190508181036000830152610325816102e9565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b600061036861036361035e8461032c565b610343565b610336565b9050919050565b6103788161034d565b82525050565b6000602082019050610393600083018461036f565b9291505056fea2646970667358221220f2a2169e9ff5b35281e8323276adc729174eda42cfb39d55a7943efc6c70485164736f6c63430008110033608060405234801561001057600080fd5b50610230806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80633ccc052214610030575b600080fd5b61004a60048036038101906100459190610140565b610060565b6040516100579190610186565b60405180910390f35b6000808290508073ffffffffffffffffffffffffffffffffffffffff1663209652556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100d591906101cd565b915050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061010d826100e2565b9050919050565b61011d81610102565b811461012857600080fd5b50565b60008135905061013a81610114565b92915050565b600060208284031215610156576101556100dd565b5b60006101648482850161012b565b91505092915050565b6000819050919050565b6101808161016d565b82525050565b600060208201905061019b6000830184610177565b92915050565b6101aa8161016d565b81146101b557600080fd5b50565b6000815190506101c7816101a1565b92915050565b6000602082840312156101e3576101e26100dd565b5b60006101f1848285016101b8565b9150509291505056fea2646970667358221220b98dab0efb759c0eea90d951be7f01d309e1c04588076d429d10680bddf1351864736f6c63430008110033a264697066735822122024666606126645f287960fe9548cc80d17258ad514d74180c7af0e1ee954bd4364736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/TransparentUpgradeableProxy.sol b/itests/contracts/TransparentUpgradeableProxy.sol new file mode 100644 index 000000000..5bb3d0e5d --- /dev/null +++ b/itests/contracts/TransparentUpgradeableProxy.sol @@ -0,0 +1,590 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +abstract contract Initializable { + uint8 private _initialized; + + bool private _initializing; + + event Initialized(uint8 version); + + modifier initializer() { + bool isTopLevelCall = !_initializing; + require( + (isTopLevelCall && _initialized < 1) || + (!Address.isContract(address(this)) && _initialized == 1), + "Initializable: contract is already initialized" + ); + _initialized = 1; + if (isTopLevelCall) { + _initializing = true; + } + _; + if (isTopLevelCall) { + _initializing = false; + emit Initialized(1); + } + } + + modifier reinitializer(uint8 version) { + require( + !_initializing && _initialized < version, + "Initializable: contract is already initialized" + ); + _initialized = version; + _initializing = true; + _; + _initializing = false; + emit Initialized(version); + } + + modifier onlyInitializing() { + require(_initializing, "Initializable: contract is not initializing"); + _; + } + + function _disableInitializers() internal virtual { + require(!_initializing, "Initializable: contract is initializing"); + if (_initialized != type(uint8).max) { + _initialized = type(uint8).max; + emit Initialized(type(uint8).max); + } + } + + function _getInitializedVersion() internal view returns (uint8) { + return _initialized; + } + + function _isInitializing() internal view returns (bool) { + return _initializing; + } +} + +contract Implementation4 is Initializable { + uint256 internal _value; + + function initialize() public initializer {} + + function setValue(uint256 _number) public { + _value = _number; + } + + function getValue() public view returns (uint256) { + return _value; + } + + fallback() external { + _value = 1; + } +} + +contract Implementation2 is Initializable { + uint256 internal _value; + + function initialize() public initializer {} + + function setValue(uint256 _number) public { + _value = _number; + } + + function getValue() public view returns (uint256) { + return _value; + } +} + +abstract contract Proxy { + function _delegate(address implementation) internal virtual { + assembly { + calldatacopy(0, 0, calldatasize()) + + let result := delegatecall( + gas(), + implementation, + 0, + calldatasize(), + 0, + 0 + ) + + returndatacopy(0, 0, returndatasize()) + + switch result + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } + + function _implementation() internal view virtual returns (address); + + function _fallback() internal virtual { + _beforeFallback(); + _delegate(_implementation()); + } + + fallback() external payable virtual { + _fallback(); + } + + receive() external payable virtual { + _fallback(); + } + + function _beforeFallback() internal virtual {} +} + +interface IBeacon { + function implementation() external view returns (address); +} + +interface IERC1822Proxiable { + function proxiableUUID() external view returns (bytes32); +} + +library Address { + function isContract(address account) internal view returns (bool) { + return account.code.length > 0; + } + + function sendValue(address payable recipient, uint256 amount) internal { + require( + address(this).balance >= amount, + "Address: insufficient balance" + ); + + (bool success, ) = recipient.call{value: amount}(""); + require( + success, + "Address: unable to send value, recipient may have reverted" + ); + } + + function functionCall( + address target, + bytes memory data + ) internal returns (bytes memory) { + return + functionCallWithValue( + target, + data, + 0, + "Address: low-level call failed" + ); + } + + function functionCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, errorMessage); + } + + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return + functionCallWithValue( + target, + data, + value, + "Address: low-level call with value failed" + ); + } + + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { + require( + address(this).balance >= value, + "Address: insufficient balance for call" + ); + (bool success, bytes memory returndata) = target.call{value: value}( + data + ); + return + verifyCallResultFromTarget( + target, + success, + returndata, + errorMessage + ); + } + + function functionStaticCall( + address target, + bytes memory data + ) internal view returns (bytes memory) { + return + functionStaticCall( + target, + data, + "Address: low-level static call failed" + ); + } + + function functionStaticCall( + address target, + bytes memory data, + string memory errorMessage + ) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = target.staticcall(data); + return + verifyCallResultFromTarget( + target, + success, + returndata, + errorMessage + ); + } + + function functionDelegateCall( + address target, + bytes memory data + ) internal returns (bytes memory) { + return + functionDelegateCall( + target, + data, + "Address: low-level delegate call failed" + ); + } + + function functionDelegateCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + (bool success, bytes memory returndata) = target.delegatecall(data); + return + verifyCallResultFromTarget( + target, + success, + returndata, + errorMessage + ); + } + + function verifyCallResultFromTarget( + address target, + bool success, + bytes memory returndata, + string memory errorMessage + ) internal view returns (bytes memory) { + if (success) { + if (returndata.length == 0) { + require(isContract(target), "Address: call to non-contract"); + } + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + function verifyCallResult( + bool success, + bytes memory returndata, + string memory errorMessage + ) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + function _revert( + bytes memory returndata, + string memory errorMessage + ) private pure { + if (returndata.length > 0) { + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } +} + +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + function getAddressSlot( + bytes32 slot + ) internal pure returns (AddressSlot storage r) { + assembly { + r.slot := slot + } + } + + function getBooleanSlot( + bytes32 slot + ) internal pure returns (BooleanSlot storage r) { + assembly { + r.slot := slot + } + } + + function getBytes32Slot( + bytes32 slot + ) internal pure returns (Bytes32Slot storage r) { + assembly { + r.slot := slot + } + } + + function getUint256Slot( + bytes32 slot + ) internal pure returns (Uint256Slot storage r) { + assembly { + r.slot := slot + } + } +} + +abstract contract ERC1967Upgrade { + bytes32 private constant _ROLLBACK_SLOT = + 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; + + bytes32 internal constant _IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + event Upgraded(address indexed implementation); + + function _getImplementation() internal view returns (address) { + return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + } + + function _setImplementation(address newImplementation) private { + require( + Address.isContract(newImplementation), + "ERC1967: new implementation is not a contract" + ); + StorageSlot + .getAddressSlot(_IMPLEMENTATION_SLOT) + .value = newImplementation; + } + + function _upgradeTo(address newImplementation) internal { + _setImplementation(newImplementation); + emit Upgraded(newImplementation); + } + + function _upgradeToAndCall( + address newImplementation, + bytes memory data, + bool forceCall + ) internal { + _upgradeTo(newImplementation); + if (data.length > 0 || forceCall) { + Address.functionDelegateCall(newImplementation, data); + } + } + + function _upgradeToAndCallUUPS( + address newImplementation, + bytes memory data, + bool forceCall + ) internal { + if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { + _setImplementation(newImplementation); + } else { + try IERC1822Proxiable(newImplementation).proxiableUUID() returns ( + bytes32 slot + ) { + require( + slot == _IMPLEMENTATION_SLOT, + "ERC1967Upgrade: unsupported proxiableUUID" + ); + } catch { + revert("ERC1967Upgrade: new implementation is not UUPS"); + } + _upgradeToAndCall(newImplementation, data, forceCall); + } + } + + bytes32 internal constant _ADMIN_SLOT = + 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + + event AdminChanged(address previousAdmin, address newAdmin); + + function _getAdmin() internal view returns (address) { + return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; + } + + function _setAdmin(address newAdmin) private { + require( + newAdmin != address(0), + "ERC1967: new admin is the zero address" + ); + StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; + } + + function _changeAdmin(address newAdmin) internal { + emit AdminChanged(_getAdmin(), newAdmin); + _setAdmin(newAdmin); + } + + bytes32 internal constant _BEACON_SLOT = + 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; + + event BeaconUpgraded(address indexed beacon); + + function _getBeacon() internal view returns (address) { + return StorageSlot.getAddressSlot(_BEACON_SLOT).value; + } + + function _setBeacon(address newBeacon) private { + require( + Address.isContract(newBeacon), + "ERC1967: new beacon is not a contract" + ); + require( + Address.isContract(IBeacon(newBeacon).implementation()), + "ERC1967: beacon implementation is not a contract" + ); + StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; + } + + function _upgradeBeaconToAndCall( + address newBeacon, + bytes memory data, + bool forceCall + ) internal { + _setBeacon(newBeacon); + emit BeaconUpgraded(newBeacon); + if (data.length > 0 || forceCall) { + Address.functionDelegateCall( + IBeacon(newBeacon).implementation(), + data + ); + } + } +} + +contract ERC1967Proxy is Proxy, ERC1967Upgrade { + constructor(address _logic, bytes memory _data) payable { + _upgradeToAndCall(_logic, _data, false); + } + + function _implementation() + internal + view + virtual + override + returns (address impl) + { + return ERC1967Upgrade._getImplementation(); + } +} + +contract TransparentUpgradeableProxy is ERC1967Proxy { + constructor(address _logic) payable ERC1967Proxy(_logic, "") { + _changeAdmin(msg.sender); + } + + modifier ifAdmin() { + if (msg.sender == _getAdmin()) { + _; + } else { + _fallback(); + } + } + + function admin() external payable ifAdmin returns (address admin_) { + _requireZeroValue(); + admin_ = _getAdmin(); + } + + function implementation() + external + payable + ifAdmin + returns (address implementation_) + { + _requireZeroValue(); + implementation_ = _implementation(); + } + + function changeAdmin(address newAdmin) external payable virtual ifAdmin { + _requireZeroValue(); + _changeAdmin(newAdmin); + } + + function upgradeTo(address newImplementation) external payable ifAdmin { + _requireZeroValue(); + _upgradeToAndCall(newImplementation, bytes(""), false); + } + + function upgradeToAndCall( + address newImplementation, + bytes calldata data + ) external payable ifAdmin { + _upgradeToAndCall(newImplementation, data, true); + } + + function _admin() internal view virtual returns (address) { + return _getAdmin(); + } + + function _beforeFallback() internal virtual override { + require( + msg.sender != _getAdmin(), + "TransparentUpgradeableProxy: admin cannot fallback to proxy target" + ); + super._beforeFallback(); + } + + function _requireZeroValue() private { + require(msg.value == 0); + } +} + +contract TestHelper { + function getValue(address proxyAddress) public returns (uint256) { + Implementation2 proxyInstance2 = Implementation2(proxyAddress); + return proxyInstance2.getValue(); + } +} + +contract TransparentUpgradeableProxyTestRunner { + function test() public { + assert(0 == getValue()); + } + + function getValue() public returns (uint256) { + Implementation4 instance4 = new Implementation4(); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(instance4) + ); + Implementation2 instance2 = new Implementation2(); + proxy.upgradeTo(address(instance2)); + //use helper because proxy admin can't call getValue() + TestHelper h = new TestHelper(); + return h.getValue(address(proxy)); + } +} diff --git a/itests/contracts/compile.sh b/itests/contracts/compile.sh index 029bff46c..31bff4b68 100644 --- a/itests/contracts/compile.sh +++ b/itests/contracts/compile.sh @@ -5,7 +5,7 @@ set -o pipefail # to compile all of the .sol files to their corresponding evm binary files stored as .hex # solc outputs to stdout a format that we just want to grab the last line of and then remove the trailing newline on that line -find . -name \*.sol -print0 | +find . -maxdepth 1 -name \*.sol -print0 | xargs -0 -I{} bash -euc -o pipefail 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' @@ -17,3 +17,7 @@ for filename in Constructor TestApp ValueSender Create2Factory DeployValueTest; solc --bin $filename.sol | tail -n5|head -n1 | tr -d "\n" > $filename.hex done +for filename in TransparentUpgradeableProxy ; do + echo $filename + solc --bin $filename.sol | tail -n1| tr -d "\n" > $filename.hex +done diff --git a/itests/fevm_test.go b/itests/fevm_test.go index 2b2a3a6d3..074f66f12 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -843,3 +843,15 @@ func TestFEVMBareTransferTriggersSmartContractLogic(t *testing.T) { // The receive() function emits one log, that's how we know we hit it. require.Len(t, receipt.Logs, 1) } + +func TestFEVMProxyUpgradeable(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install transparently upgradeable proxy + proxyFilename := "contracts/TransparentUpgradeableProxy.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, proxyFilename) + + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "test()", []byte{}) + require.NoError(t, err) +}