Skip to main content
Version: 20.0.0

Examples demonstrating transfers between various address types

In Tezos, a transfer operation transfers tokens between two addresses.

When the Babylon/proto005 protocol amendment came into effect, it changed how token transfer involving KT1 addresses work. The transfer of tokens from a KT1 account is completed by calling the KT1's smart contract do method. The do method takes a lambda function, and it is the logic of this function that causes the desired transfer of tokens to happen.

The Taquito integration tests can be useful to see how this works.

Transfer from an implicit tz1 address to a tz1 address

This is the simplest token transfer scenario

await Tezos.contract.transfer({ to: contract.address, amount: 1 });

In the following example, we transfer 0.5ꜩ from a tz1aaYoabvj2DQtpHz74Z83fSNjY29asdBfZ address that signs the operation to tz1h3rQ8wBxFd8L9B3d7Jhaawu6Z568XU3xY.

Live Editor
Result

Transfers involving "originated" KT1 addresses

Pre-Babylon/proto005 "script-less" KT1 addresses were common. This situation changed when the Tezos blockchain migrated to the new Babylon/proto005 protocol.

During the migration from proto004 to proto005, all KT1 addresses migrated so that they got a contract called manager.tz. This change meant that there are no longer any "script-less" KT1 addresses in Tezos.

A call to the KT1's smart contracts' do method is required to transfer tokens from KT1 addresses with the new manager.tz contract. The do method takes a lambda function, and it is this lambda function that causes changes to occur in the KT1 address.

The examples following apply only to KT1 addresses migrated as part of the Babylon/proto005 upgrade. Transfers involving other types of smart-contracts depend on those contracts specifically.

Transfer 0.00005 (50 mutez) tokens from a KT1 address to a tz1 address

Sending 50 mutez from kt1... to tz1eY5Aqa1kXDFoiebL28emyXFoneAoVg1zh.

Example transfer from a KT1 to a tz1 address on Carthage/Proto006

const contract = await Tezos.contract.at('kt1...');
await contract.methodsObject
.do(transferImplicit('tz1eY5Aqa1kXDFoiebL28emyXFoneAoVg1zh', 50))
.send({ amount: 0 });

Where transferImplicit is a function that returns the necessary Michelson lambda. It looks like this:

export const transferImplicit = (key: string, mutez: number) => {
return [
{ prim: 'DROP' },
{ prim: 'NIL', args: [{ prim: 'operation' }] },
{
prim: 'PUSH',
args: [{ prim: 'key_hash' }, { string: key }],
},
{ prim: 'IMPLICIT_ACCOUNT' },
{
prim: 'PUSH',
args: [{ prim: 'mutez' }, { int: `${mutez}` }],
},
{ prim: 'UNIT' },
{ prim: 'TRANSFER_TOKENS' },
{ prim: 'CONS' },
];
};

Transfer 0.000001 (1 mutez) tokens from a KT1 address to a KT1 address

Sending 1 mutez to KT1KLbEeEgW5h1QLkPuPvqdgurHx6v4hGyic from KT1...

Example for Babylon/Proto005 or higher

const contract = await Tezos.contract.at('KT1...');
await contract.methodsObject
.do(transferToContract('KT1KLbEeEgW5h1QLkPuPvqdgurHx6v4hGyic', 1))
.send({ amount: 0 });

Where transferToContract is a function that looks like this:

export const transferToContract = (key: string, amount: number) => {
return [
{ prim: 'DROP' },
{ prim: 'NIL', args: [{ prim: 'operation' }] },
{
prim: 'PUSH',
args: [{ prim: 'address' }, { string: key }],
},
{ prim: 'CONTRACT', args: [{ prim: 'unit' }] },
[
{
prim: 'IF_NONE',
args: [[[{ prim: 'UNIT' }, { prim: 'FAILWITH' }]], []],
},
],
{
prim: 'PUSH',
args: [{ prim: 'mutez' }, { int: `${amount}` }],
},
{ prim: 'UNIT' },
{ prim: 'TRANSFER_TOKENS' },
{ prim: 'CONS' },
];
};

Provide detailed feedback