Send value and data to an unknown address inside the contract

#support

Which is the best way to send value and data to an unknown address inside the contract?

function call0(address destination, uint value, uint dataLength, bytes data) internal returns (bool) {
    return (destination.call.value(tx.value)(tx.data))
}


function call1(address destination, uint value, uint dataLength, bytes data) internal returns (bool) {
        bool result;
        assembly {
            let x := mload(0x40)   // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
            let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
            result := call(
                sub(gas, 34710),   // 34710 is the value that solidity is currently emitting
                                   // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
                                   // callNewAccountGas (25000, in case the destination address does not exist and needs creating)
                destination,
                value,
                d,
                dataLength,        // Size of the input (in bytes) - this is what fixes the padding problem
                x,
                0                  // Output is ignored, therefore the output size is zero
            )
        }
        return result;
    }

call0 or call1 or other methods?

2 Likes

After EIP-1884, the call1 should pay more gas now.

1 Like

call1 can help stop the short address attack.

However, using a fixed amount of gas caused incompatibility problems.

After EIP-1884, the call1 should pay more gas now.

1 Like

Hi @Vie,

If you are calling a function on a contract you could use: functionCallWithValue

To just send value to an address you could look at sendValue

1 Like

Thank you @abcoathup, it’s Useful for me

You should do something similar to your call0 example, although you probably shouldn’t be using tx.data, nor tx.value.

This is what our sendValue helper does:

If you want to include data you could define the following function:

function call3(address recipient, bytes memory data) public payable {
    (bool success, ) = recipient.call{ value: msg.value }(data);
    require(success);
}

(Note the newer .call{ value: v } syntax, that you should replace with .call.value(v) on older Solidity versions.)

You could replace msg.value by some other amount, but using tx.value is most likely wrong.

2 Likes

@frangio thank you for your reply. it’s useful for me.

1 Like