call
call(a, b, c, d, e, f, g)
is used to send Ether to an EOA or a smart contract, and also, send a specified calldata
alongside the transaction to be executed when the smart contract receives the call.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract CalledContract {
uint256 public storedNumber;
receive () external payable {}
function setNumber(uint256 num) external {
assembly {
sstore(0x00, num)
}
}
function setNumberWithEther(uint256 num) external payable {
assembly {
if eq(callvalue(), 0) { revert(0x00, 0x00) }
sstore(0x00, num)
}
}
}
contract CallerContract {
address public calledContract;
receive () external payable {}
// Deploy with address of CalledContract.
constructor(address _address) {
assembly {
sstore(0x00, _address)
}
}
function callContract(uint256 num) public {
assembly {
// Start at 0x1c, this is the first calldata entry.
// Call setNumber(uint256).
mstore(0x00, 0x3fb5c1cb)
mstore(0x20, num)
// To learn about calldata encoding: https://rb.gy/vmzhck.
// Read 32 + 4 bytes.
let success := call(gas(), sload(0x00), 0, 0x1c, 0x24, 0, 0)
if iszero(success) { revert(0x00, 0x00) }
// In Called.sol, number == num.
}
}
function callContractWithEther(uint256 num) public payable {
assembly {
// Start at 0x1c, this is the first calldata entry.
// Call setNumberWithEther(uint256).
mstore(0x00, 0xcc95ae02)
mstore(0x20, num)
// To learn about calldata encoding: https://rb.gy/vmzhck.
// Read 32 + 4 bytes.
let success := call(gas(), sload(0x00), callvalue(), 0x1c, 0x24, 0, 0)
if iszero(success) { revert(0x00, 0x00) }
// In Called.sol, number == num.
}
}
}
callvalue()
is used to retrieve msg.value
in Yul.