Files
atomic-swap/ethereum/check_swap_creator_contract.go
2023-04-24 17:06:10 -04:00

135 lines
19 KiB
Go

// Copyright 2023 The AthanorLabs/atomic-swap Authors
// SPDX-License-Identifier: LGPL-3.0-only
package contracts
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/athanorlabs/atomic-swap/common"
"github.com/athanorlabs/go-relayer/impls/gsnforwarder"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
// expectedSwapCreatorBytecodeHex is generated by deploying an instance of SwapCreator.sol
// with the trustedForwarder address set to all zeros and reading back the bytecode. See
// the unit test TestExpectedSwapCreatorBytecodeHex if you need to update this value.
const (
expectedSwapCreatorBytecodeHex = "6080604052600436106100865760003560e01c806373e4771c1161005957806373e4771c14610145578063b32d1b4f1461016e578063c41e46cf146101ab578063eb84e7f2146101db578063fcaf229c1461021857610086565b80631e6c5acc1461008b57806356c022bb146100b4578063572b6c05146100df5780635cb969161461011c575b600080fd5b34801561009757600080fd5b506100b260048036038101906100ad9190611610565b610241565b005b3480156100c057600080fd5b506100c96105c4565b6040516100d69190611661565b60405180910390f35b3480156100eb57600080fd5b506101066004803603810190610101919061167c565b6105e8565b60405161011391906116c4565b60405180910390f35b34801561012857600080fd5b50610143600480360381019061013e9190611610565b610640565b005b34801561015157600080fd5b5061016c600480360381019061016791906116df565b610766565b005b34801561017a57600080fd5b5061019560048036038101906101909190611735565b6109ac565b6040516101a291906116c4565b60405180910390f35b6101c560048036038101906101c09190611775565b610ab1565b6040516101d2919061183a565b60405180910390f35b3480156101e757600080fd5b5061020260048036038101906101fd9190611855565b610ec4565b60405161020f91906118f9565b60405180910390f35b34801561022457600080fd5b5061023f600480360381019061023a9190611914565b610ee4565b005b6000826040516020016102549190611a35565b604051602081830303815290604052805190602001209050600080600083815260200190815260200160002060009054906101000a900460ff169050600060038111156102a4576102a3611882565b5b8160038111156102b7576102b6611882565b5b036102ee576040517f1115766700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038081111561030157610300611882565b5b81600381111561031457610313611882565b5b0361034b576040517f066916a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff16146103b4576040517f2919448600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360a00151421080156103f9575083608001514211806103f85750600260038111156103e3576103e2611882565b5b8160038111156103f6576103f5611882565b5b145b5b15610430576040517f65430c1e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61043e838560600151611061565b82827e7c875846b687732a7579c19bb1dade66cd14e9f4f809565e2b2b5e76c72b4f60405160405180910390a3600360008084815260200190815260200160002060006101000a81548160ff021916908360038111156104a1576104a0611882565b5b0217905550600073ffffffffffffffffffffffffffffffffffffffff168460c0015173ffffffffffffffffffffffffffffffffffffffff160361053257836000015173ffffffffffffffffffffffffffffffffffffffff166108fc8560e001519081150290604051600060405180830381858888f1935050505015801561052c573d6000803e3d6000fd5b506105be565b8360c0015173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85600001518660e001516040518363ffffffff1660e01b8152600401610579929190611abf565b6020604051808303816000875af1158015610598573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bc9190611b14565b505b50505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b61064a82826110ab565b600073ffffffffffffffffffffffffffffffffffffffff168260c0015173ffffffffffffffffffffffffffffffffffffffff16036106d657816020015173ffffffffffffffffffffffffffffffffffffffff166108fc8360e001519081150290604051600060405180830381858888f193505050501580156106d0573d6000803e3d6000fd5b50610762565b8160c0015173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83602001518460e001516040518363ffffffff1660e01b815260040161071d929190611abf565b6020604051808303816000875af115801561073c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107609190611b14565b505b5050565b61076f336105e8565b6107a5576040517ffc5d4daa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107af83836110ab565b600073ffffffffffffffffffffffffffffffffffffffff168360c0015173ffffffffffffffffffffffffffffffffffffffff160361088d57826020015173ffffffffffffffffffffffffffffffffffffffff166108fc828560e001516108159190611b70565b9081150290604051600060405180830381858888f19350505050158015610840573d6000803e3d6000fd5b503273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610887573d6000803e3d6000fd5b506109a7565b8260c0015173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460200151838660e001516108c29190611b70565b6040518363ffffffff1660e01b81526004016108df929190611abf565b6020604051808303816000875af11580156108fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109229190611b14565b508260c0015173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb32836040518363ffffffff1660e01b8152600401610962929190611ba4565b6020604051808303816000875af1158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a59190611b14565b505b505050565b60008060016000601b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179860001b7ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414180610a0857610a07611bcd565b5b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798890960001b60405160008152602001604052604051610a4b9493929190611c8c565b6020604051602081039080840390855afa158015610a6d573d6000803e3d6000fd5b5050506020604051035190508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161491505092915050565b6000808303610aec576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610b5e57348314610b59576040517faa7feadc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610be0565b8373ffffffffffffffffffffffffffffffffffffffff166323b872dd3330866040518463ffffffff1660e01b8152600401610b9b93929190611cd1565b6020604051808303816000875af1158015610bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bde9190611b14565b505b6000801b891480610bf357506000801b88145b15610c2a576040517f378c37da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603610c90576040517f044bc28000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000861480610c9f5750600085145b15610cd6576040517f7fee1bc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061012001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018b81526020018a81526020018842610d349190611d08565b8152602001878942610d469190611d08565b610d509190611d08565b81526020018673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152509050600081604051602001610d909190611a35565b60405160208183030381529060405280519060200120905060006003811115610dbc57610dbb611882565b5b60008083815260200190815260200160002060009054906101000a900460ff166003811115610dee57610ded611882565b5b14610e25576040517f734530ce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f91446ce035ac29998b5473504609a5ef5e961005daba4630a1684b63be848f56818c8c85608001518660a001518760c001518860e00151604051610e709796959493929190611d3c565b60405180910390a1600160008083815260200190815260200160002060006101000a81548160ff02191690836003811115610eae57610ead611882565b5b0217905550809250505098975050505050505050565b60006020528060005260406000206000915054906101000a900460ff1681565b600081604051602001610ef79190611a35565b60405160208183030381529060405280519060200120905060016003811115610f2357610f22611882565b5b60008083815260200190815260200160002060009054906101000a900460ff166003811115610f5557610f54611882565b5b14610f8c576040517f1fc1f6a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff1614610ff5576040517f2919448600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260008083815260200190815260200160002060006101000a81548160ff0219169083600381111561102b5761102a611882565b5b0217905550807f5fc23b25552757626e08b316cc2387ad1bc70ee1594af7204db4ce0c39f5d15f60405160405180910390a25050565b6110718260001c8260001c6109ac565b6110a7576040517fabab6bd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b6000826040516020016110be9190611a35565b604051602081830303815290604052805190602001209050600080600083815260200190815260200160002060009054906101000a900460ff1690506000600381111561110e5761110d611882565b5b81600381111561112157611120611882565b5b03611158576040517f1115766700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038081111561116b5761116a611882565b5b81600381111561117e5761117d611882565b5b036111b5576040517f066916a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836020015173ffffffffffffffffffffffffffffffffffffffff166111d861134e565b73ffffffffffffffffffffffffffffffffffffffff1614611225576040517f68e2c81200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83608001514210801561125d57506002600381111561124757611246611882565b5b81600381111561125a57611259611882565b5b14155b15611294576040517fd71d60b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360a0015142106112d1576040517f497df9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112df838560400151611061565b82827f38d6042dbdae8e73a7f6afbabd3fbe0873f9f5ed3cd71294591c3908c2e65fee60405160405180910390a3600360008084815260200190815260200160002060006101000a81548160ff0219169083600381111561134357611342611882565b5b021790555050505050565b6000611359336105e8565b1561136d57601436033560601c905061137c565b611375611380565b905061137d565b5b90565b600033905090565b6000604051905090565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6113e58261139c565b810181811067ffffffffffffffff82111715611404576114036113ad565b5b80604052505050565b6000611417611388565b905061142382826113dc565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061145382611428565b9050919050565b61146381611448565b811461146e57600080fd5b50565b6000813590506114808161145a565b92915050565b6000819050919050565b61149981611486565b81146114a457600080fd5b50565b6000813590506114b681611490565b92915050565b6000819050919050565b6114cf816114bc565b81146114da57600080fd5b50565b6000813590506114ec816114c6565b92915050565b60006114fd82611428565b9050919050565b61150d816114f2565b811461151857600080fd5b50565b60008135905061152a81611504565b92915050565b6000610120828403121561154757611546611397565b5b61155261012061140d565b9050600061156284828501611471565b600083015250602061157684828501611471565b602083015250604061158a848285016114a7565b604083015250606061159e848285016114a7565b60608301525060806115b2848285016114dd565b60808301525060a06115c6848285016114dd565b60a08301525060c06115da8482850161151b565b60c08301525060e06115ee848285016114dd565b60e083015250610100611603848285016114dd565b6101008301525092915050565b600080610140838503121561162857611627611392565b5b600061163685828601611530565b925050610120611648858286016114a7565b9150509250929050565b61165b816114f2565b82525050565b60006020820190506116766000830184611652565b92915050565b60006020828403121561169257611691611392565b5b60006116a08482850161151b565b91505092915050565b60008115159050919050565b6116be816116a9565b82525050565b60006020820190506116d960008301846116b5565b92915050565b600080600061016084860312156116f9576116f8611392565b5b600061170786828701611530565b935050610120611719868287016114a7565b92505061014061172b868287016114dd565b9150509250925092565b6000806040838503121561174c5761174b611392565b5b600061175a858286016114dd565b925050602061176b858286016114dd565b9150509250929050565b600080600080600080600080610100898b03121561179657611795611392565b5b60006117a48b828c016114a7565b98505060206117b58b828c016114a7565b97505060406117c68b828c01611471565b96505060606117d78b828c016114dd565b95505060806117e88b828c016114dd565b94505060a06117f98b828c0161151b565b93505060c061180a8b828c016114dd565b92505060e061181b8b828c016114dd565b9150509295985092959890939650565b61183481611486565b82525050565b600060208201905061184f600083018461182b565b92915050565b60006020828403121561186b5761186a611392565b5b6000611879848285016114a7565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106118c2576118c1611882565b5b50565b60008190506118d3826118b1565b919050565b60006118e3826118c5565b9050919050565b6118f3816118d8565b82525050565b600060208201905061190e60008301846118ea565b92915050565b6000610120828403121561192b5761192a611392565b5b600061193984828501611530565b91505092915050565b61194b81611448565b82525050565b61195a81611486565b82525050565b611969816114bc565b82525050565b611978816114f2565b82525050565b610120820160008201516119956000850182611942565b5060208201516119a86020850182611942565b5060408201516119bb6040850182611951565b5060608201516119ce6060850182611951565b5060808201516119e16080850182611960565b5060a08201516119f460a0850182611960565b5060c0820151611a0760c085018261196f565b5060e0820151611a1a60e0850182611960565b50610100820151611a2f610100850182611960565b50505050565b600061012082019050611a4b600083018461197e565b92915050565b6000819050919050565b6000611a76611a71611a6c84611428565b611a51565b611428565b9050919050565b6000611a8882611a5b565b9050919050565b6000611a9a82611a7d565b9050919050565b611aaa81611a8f565b82525050565b611ab9816114bc565b82525050565b6000604082019050611ad46000830185611aa1565b611ae16020830184611ab0565b9392505050565b611af1816116a9565b8114611afc57600080fd5b50565b600081519050611b0e81611ae8565b92915050565b600060208284031215611b2a57611b29611392565b5b6000611b3884828501611aff565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611b7b826114bc565b9150611b86836114bc565b9250828203905081811115611b9e57611b9d611b41565b5b92915050565b6000604082019050611bb96000830185611652565b611bc66020830184611ab0565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000819050919050565b60008160001b9050919050565b6000611c2e611c29611c2484611bfc565b611c06565b611486565b9050919050565b611c3e81611c13565b82525050565b6000819050919050565b600060ff82169050919050565b6000611c76611c71611c6c84611c44565b611a51565b611c4e565b9050919050565b611c8681611c5b565b82525050565b6000608082019050611ca16000830187611c35565b611cae6020830186611c7d565b611cbb604083018561182b565b611cc8606083018461182b565b95945050505050565b6000606082019050611ce66000830186611652565b611cf36020830185611652565b611d006040830184611ab0565b949350505050565b6000611d13826114bc565b9150611d1e836114bc565b9250828201905080821115611d3657611d35611b41565b5b92915050565b600060e082019050611d51600083018a61182b565b611d5e602083018961182b565b611d6b604083018861182b565b611d786060830187611ab0565b611d856080830186611ab0565b611d9260a0830185611652565b611d9f60c0830184611ab0565b9897505050505050505056fea264697066735822122084f522d05ed6af1060846f3e30d11805736fb4d34a12fcf1a991eced80ebd24a64736f6c63430008130033" //nolint:lll
ethAddrByteLen = len(ethcommon.Address{}) // 20 bytes
)
// forwarderAddrIndices is a slice of the start indices where the trusted forwarder
// address is compiled into the deployed contract byte code. When verifying the bytecode
// of a deployed contract, we need special treatment for these identical 20-byte address
// blocks. See TestForwarderAddrIndexes to update the values.
var forwarderAddrIndices = []int{1490, 1528}
var (
errInvalidSwapCreatorContract = errors.New("given contract address does not contain correct SwapCreator code")
errInvalidForwarderContract = errors.New("given contract address does not contain correct Forwarder code")
)
// CheckSwapCreatorContractCode checks that the bytecode at the given address matches the
// SwapCreator.sol contract. The trusted forwarder address that the contract was deployed
// with is parsed out from the byte code and returned.
func CheckSwapCreatorContractCode(
ctx context.Context,
ec *ethclient.Client,
contractAddr ethcommon.Address,
) (ethcommon.Address, error) {
code, err := ec.CodeAt(ctx, contractAddr, nil)
if err != nil {
return ethcommon.Address{}, err
}
expectedCode := ethcommon.FromHex(expectedSwapCreatorBytecodeHex)
if len(code) != len(expectedCode) {
return ethcommon.Address{}, fmt.Errorf("length mismatch: %w", errInvalidSwapCreatorContract)
}
allZeroAddr := ethcommon.Address{}
// we fill this in with the trusted forwarder that the contract was deployed with
var forwarderAddr ethcommon.Address
for i, addrIndex := range forwarderAddrIndices {
curAddr := code[addrIndex : addrIndex+ethAddrByteLen]
if i == 0 {
// initialise the trusted forwarder address on the first index
copy(forwarderAddr[:], curAddr)
} else {
// check that any remaining forwarder addresses match the one we found at the first index
if !bytes.Equal(curAddr, forwarderAddr[:]) {
return ethcommon.Address{}, errInvalidSwapCreatorContract
}
}
// Zero out the trusted forwarder address in the code, so that we can compare the
// read in byte code with a copy of the contract code that was deployed using an
// all-zero trusted forwarder address. curAddr and code have the same backing
// array, so we are updating expectedCode as well here:
copy(curAddr, allZeroAddr[:])
}
// Now that the trusted forwarder addresses have been zeroed out, the read-in contract code should
// match the expected code.
if !bytes.Equal(expectedCode, code) {
return ethcommon.Address{}, errInvalidSwapCreatorContract
}
if (forwarderAddr == ethcommon.Address{}) {
return forwarderAddr, nil
}
err = CheckForwarderContractCode(ctx, ec, forwarderAddr)
if err != nil {
return ethcommon.Address{}, err
}
// return the trusted forwarder address that was parsed from the deployed contract byte code
return forwarderAddr, nil
}
// CheckForwarderContractCode checks that the trusted forwarder contract used by
// the given swap contract has the expected bytecode.
func CheckForwarderContractCode(
ctx context.Context,
ec *ethclient.Client,
contractAddr ethcommon.Address,
) error {
// mainnet override - since the forwarder contract deployed on mainnet is compiled
// with solidity 0.8.7, but we're using 0.8.19 for SwapCreator.sol, we can just
// check that the address is what's expected.
chainID, err := ec.ChainID(ctx)
if err != nil {
return err
}
if contractAddr == common.MainnetConfig().ForwarderAddr && chainID.Uint64() == common.MainnetChainID {
return nil
}
code, err := ec.CodeAt(ctx, contractAddr, nil)
if err != nil {
return err
}
expectedCode := ethcommon.FromHex(gsnforwarder.ForwarderMetaData.Bin)
// expectedCode is the compiled code, while code is the deployed bytecode.
// the deployed bytecode is a subset of the compiled code.
if !bytes.Equal(expectedCode[705:9585], code) {
return errInvalidForwarderContract
}
return nil
}