diff --git a/precompiles/ibc/abi.json b/precompiles/ibc/abi.json index f4e871a3b3..5c2809d2dc 100644 --- a/precompiles/ibc/abi.json +++ b/precompiles/ibc/abi.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"},{"internalType":"uint64","name":"timeoutTimestamp","type":"uint64"},{"internalType":"string","name":"memo","type":"string"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"memo","type":"string"}],"name":"transferWithDefaultTimeout","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"}] +[{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"},{"internalType":"uint64","name":"timeoutTimestamp","type":"uint64"},{"internalType":"string","name":"memo","type":"string"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"memo","type":"string"}],"name":"transferWithDefaultTimeout","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] diff --git a/precompiles/ibc/ibc.go b/precompiles/ibc/ibc.go index a7e24d4aed..e3783717c2 100644 --- a/precompiles/ibc/ibc.go +++ b/precompiles/ibc/ibc.go @@ -73,6 +73,10 @@ func NewPrecompile( } func (p PrecompileExecutor) Execute(ctx sdk.Context, method *abi.Method, caller common.Address, callingContract common.Address, args []interface{}, value *big.Int, readOnly bool, evm *vm.EVM, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) { + if err = pcommon.ValidateNonPayable(value); err != nil { + return nil, 0, err + } + if readOnly { return nil, 0, errors.New("cannot call IBC precompile from staticcall") } diff --git a/precompiles/ibc/ibc_test.go b/precompiles/ibc/ibc_test.go index 08a2313775..6b57112f6b 100644 --- a/precompiles/ibc/ibc_test.go +++ b/precompiles/ibc/ibc_test.go @@ -126,6 +126,14 @@ func TestPrecompile_Run(t *testing.T) { wantErr: true, wantErrMsg: "cannot delegatecall IBC", }, + { + name: "failed transfer: value is not nil", + fields: fields{transferKeeper: &MockTransferKeeper{}}, + args: args{caller: senderEvmAddress, callingContract: common.Address{}, input: commonArgs.input, suppliedGas: 1000000, value: big.NewInt(100), isFromDelegateCall: true}, + wantBz: nil, + wantErr: true, + wantErrMsg: "sending funds to a non-payable function", + }, { name: "failed transfer: empty sourcePort", fields: fields{transferKeeper: &MockTransferKeeper{}}, @@ -357,6 +365,14 @@ func TestTransferWithDefaultTimeoutPrecompile_Run(t *testing.T) { wantErr: true, wantErrMsg: "cannot delegatecall IBC", }, + { + name: "failed transfer: value is not nil", + fields: fields{transferKeeper: &MockTransferKeeper{}}, + args: args{caller: senderEvmAddress, callingContract: common.Address{}, input: commonArgs.input, suppliedGas: 1000000, value: big.NewInt(100), isFromDelegateCall: true}, + wantBz: nil, + wantErr: true, + wantErrMsg: "sending funds to a non-payable function", + }, { name: "failed transfer: empty sourcePort", fields: fields{transferKeeper: &MockTransferKeeper{}},