Skip to main content

Transfer Tokens

The Call Context in smart contracts introduces two vital methods - balances() and allowance() - to manage token balances efficiently. Understanding how to use these can be foundational in setting up smart contracts, as demonstrated in the dividend smart contract example.

Methods Overview

1. balances() Method:

  • Functionality: Fetch the present asset balances regulated by the smart contract.
  • Access: Through the ScBalances proxy.

2. allowance() Method:

  • Functionality: Verify the caller assets that the current smart contract function can use.
  • Transfer Requirement: Assets are not automatically transferred; the function must instigate the transfer explicitly within the allowed limit.
  • Access: Through the ScBalances proxy.

3. transfer_allowed() Method:

  • Functionality: Facilitate asset transfers from the caller's on-chain account to another on-chain account.
  • Proxy: uses the ScTransfer proxy, a mutable variant of ScBalances.
  • Application: In the dividend contract, it aids in distributing iotas to member accounts.

Dividend Smart Contract Example

The dividend smart contract operates on a principle of equitable asset distribution to its members based on predefined factors. Here's how it works:

  1. Setup: Establish a list of members with associated address/factor pairs and calculate the total factor sum.
  2. Function: The divide() function manages the dividend distribution.
  3. Dividend Allocation:
    • Input: Iotas sent to the divide() function.
    • Distribution: Proportional to the individual's factor.
    • Example: For factors A:50, B:30, and C:20 (total 100):
      • A receives: 50/100 of the input iotas.
      • B receives: 30/100 of the input iotas.
      • C receives: 20/100 of the input iotas.

In this system, asset distribution is transparent, fair, and automated, ensuring a streamlined division process.

Here is the divide function:

// 'divide' is a function that will take any iotas it receives and properly
// disperse them to the accounts in the member list according to the dispersion
// factors associated with these accounts.
// Anyone can send iotas to this function and they will automatically be
// divided over the member list. Note that this function does not deal with
// fractions. It simply truncates the calculated amount to the nearest lower
// integer and keeps any remaining tokens in the sender account.
func funcDivide(ctx wasmlib.ScFuncContext, f *DivideContext) {
// Create an ScBalances proxy to the allowance balances for this
// smart contract.
var allowance *wasmlib.ScBalances = ctx.Allowance()

// Retrieve the amount of plain iota tokens from the account balance.
var amount uint64 = allowance.BaseTokens()

// Retrieve the pre-calculated totalFactor value from the state storage.
var totalFactor uint64 = f.State.TotalFactor().Value()

// Get the proxy to the 'members' map in the state storage.
var members MapAddressToMutableUint64 = f.State.Members()

// Get the proxy to the 'memberList' array in the state storage.
var memberList ArrayOfMutableAddress = f.State.MemberList()

// Determine the current length of the memberList array.
var size uint32 = memberList.Length()

// Loop through all indexes of the memberList array.
for i := uint32(0); i < size; i++ {
// Retrieve the next indexed address from the memberList array.
var address wasmtypes.ScAddress = memberList.GetAddress(i).Value()

// Retrieve the factor associated with the address from the members map.
var factor uint64 = members.GetUint64(address).Value()

// Calculate the fair share of tokens to disperse to this member based on the
// factor we just retrieved. Note that the result will been truncated.
var share uint64 = amount * factor / totalFactor

// Is there anything to disperse to this member?
if share > 0 {
// Yes, so let's set up an ScTransfer map proxy that transfers the
// calculated amount of tokens.
var transfer *wasmlib.ScTransfer = wasmlib.NewScTransferBaseTokens(share)

// Perform the actual transfer of tokens from the caller allowance
// to the member account.
ctx.TransferAllowed(address.AsAgentID(), transfer)
}
}
}