Managing values
Sending and receiving value
Value in Solidity is represented by uint128
.
Note
On Polkadot, contracts can be compiled with a different type for T::Balance
. If you
need support for a different type, please raise an
issue.
Checking your balance
Polkadot cannot check the balance for contracts other than the current one. If you need to check the balance of another contract, then add a balance function to that contract like the one below, and call that function instead.
function balance() public returns (uint128) {
return address(this).balance;
}
On Solana, the balance of an account can be accessed using the lamports
member of the AccountInfo
struct. Every account whose value we want to check must be declared with an account annotation.
@account(my_acc)
function balance() external returns (uint64) {
return tx.accounts.my_acc.lamports;
}
Creating contracts with an initial value
You can specify the value you want to be deposited in the new contract by
specifying {value: 100 ether}
before the constructor arguments. This is
explained in sending value to the new contract.
Sending value with an external call
You can specify the value you want to be sent along with the function call by
specifying {value: 100 ether}
before the function arguments. This is
explained in passing value and gas with external calls.
Sending value using send()
and transfer()
The send()
and transfer()
functions are available as method on a
address payable
variable. The single arguments is the amount of value you
would like to send. The difference between the two functions is what happens
in the failure case: transfer()
will revert the current call, send()
returns a bool
which will be false
.
In order for the receiving contract to receive the value, it needs a receive()
function, see fallback() and receive() function.
Here is an example:
contract A {
B other;
constructor() {
other = new B();
bool complete = payable(other).transfer(100);
if (!complete) {
// oops
}
// if the following fails, our transaction will fail
other.send(100);
}
}
contract B {
receive() payable external {
// ..
}
}
Note
On Subtrate, this uses the seal_transfer()
mechanism rather than seal_call()
, since this
does not come with gas overhead. This means the receive()
function is not required in the
receiving contract, and it will not be called if it is present. If you want the receive()
function to be called, use address.call{value: 100}("")
instead.
On Solana, there are no transfer
and send
functions. In order to alter the balance of accounts,
one might increment or decrement the lamports
field from the AccountInfo
struct directly. This
is only possible if the accounts whose balance is being changed are owned by the program.
@mutableAccount(acc1)
@mutableAccount(acc2)
function transfer(uint64 amount) external {
tx.accounts.acc1.lamports += amount;
tx.accounts.acc2.lamports -= amount;
}