Skip to content

Commit

Permalink
Updated docs from Carthagenet to Delphinet and redeployed cexample co…
Browse files Browse the repository at this point in the history
…ntracts to Delphinet
  • Loading branch information
claudebarde committed Jan 6, 2021
1 parent 751522d commit a29809e
Show file tree
Hide file tree
Showing 17 changed files with 1,075 additions and 848 deletions.
206 changes: 126 additions & 80 deletions docs/drain_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,108 +3,154 @@ title: Drain an account
author: Roxane Letourneau
---

In this section, we show how to transfer all tokens from one account (implicit or originated) to another so that the source account balance is zero.
In this section, we show how to transfer all tokens from one account (implicit or originated) to another so that the source account balance is zero.

## Draining implicit accounts (tz1, tz2, tz3)

We want to "empty" an implicit account by sending all of its tokens to another account. It can be tricky to empty a tezos account completely because the gas fee must be subtracted from the account balance.
We want to "empty" an implicit account by sending all of its tokens to another account. It can be tricky to empty a tezos account completely because the gas fee must be subtracted from the account balance.

To do so, we first need to estimate the fees related to this operation. The `estimate` property of the `TezosToolkit` provides access to operation estimation utilities. Calling the `transfer` method will return an instance of the `Estimate` class and its `suggestedFeeMutez` property will allow us to know the fee associated with the operation.

Once we know the associated fees, we can calculate the maximum amount that needs to be sent to drain the account by subtracting these fees from the account balance.

Finally, we can do the transfer operation and use the maximum amount we just calculated as the `amount` parameter of the `transfer` function.
Finally, we can do the transfer operation and use the maximum amount we just calculated as the `amount` parameter of the `transfer` function.

:::note
In the following example, the account we want to empty is not yet revealed. We need to keep in mind that there are fees related to a reveal operation. This is why we are subtracting 1420 mutez from the balance as it will be used as reveal fees.
In the following example, the account we want to empty is not yet revealed. We need to keep in mind that there are fees related to a reveal operation. This is why we are subtracting 1420 mutez from the balance as it will be used as reveal fees.

**If the account to drain has already been revealed, you must not subtract this amount (1420 mutez) from the balance.**
:::

```js live noInline
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/carthagenet');

Tezos.signer.publicKeyHash()
.then( address => {
Tezos.tz.getBalance(address)
.then( balance => {
println(`The account we want to drain is ${address}.\nIts initial balance is ${balance.toNumber() / 1000000} ꜩ.`)
Tezos.estimate.transfer({ to: 'tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr', amount: balance.toNumber() - 1420, mutez : true})
.then(estimate =>{
//Subtract 1420 mutez for fees related to the reveal operation
const maxAmount = balance.minus(estimate.suggestedFeeMutez).toNumber() - 1420;
println(`The estimated fees related to the emptying operation are ${estimate.suggestedFeeMutez} mutez.\nConsidering the fees, the amount we need to send to empty the account is ${maxAmount / 1000000} ꜩ.`)
return Tezos.contract.transfer({ to: 'tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr', mutez:true, amount: maxAmount, fee: estimate.suggestedFeeMutez, gasLimit: estimate.gasLimit, storageLimit: 0 })
}).then(op => {
println(`Waiting for confirmation of the draining operation...`);
return op.confirmation(1).then(() => op.hash);
}).then(hash => {
println(`The account has been emptied.`)
return Tezos.tz.getBalance(address)
}).then( finalBalance => {
println(`The balance is now ${finalBalance.toNumber() / 1000000} ꜩ.`)
})})}).catch(error => println(`Error: ${JSON.stringify(error, null, 2)}`));
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/delphinet');

Tezos.signer
.publicKeyHash()
.then((address) => {
Tezos.tz.getBalance(address).then((balance) => {
println(
`The account we want to drain is ${address}.\nIts initial balance is ${
balance.toNumber() / 1000000
} ꜩ.`
);
Tezos.estimate
.transfer({
to: 'tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr',
amount: balance.toNumber() - 1420,
mutez: true,
})
.then((estimate) => {
//Subtract 1420 mutez for fees related to the reveal operation
const maxAmount = balance.minus(estimate.suggestedFeeMutez).toNumber() - 1420;
println(
`The estimated fees related to the emptying operation are ${
estimate.suggestedFeeMutez
} mutez.\nConsidering the fees, the amount we need to send to empty the account is ${
maxAmount / 1000000
} ꜩ.`
);
return Tezos.contract.transfer({
to: 'tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr',
mutez: true,
amount: maxAmount,
fee: estimate.suggestedFeeMutez,
gasLimit: estimate.gasLimit,
storageLimit: 0,
});
})
.then((op) => {
println(`Waiting for confirmation of the draining operation...`);
return op.confirmation(1).then(() => op.hash);
})
.then((hash) => {
println(`The account has been emptied.`);
return Tezos.tz.getBalance(address);
})
.then((finalBalance) => {
println(`The balance is now ${finalBalance.toNumber() / 1000000} ꜩ.`);
});
});
})
.catch((error) => println(`Error: ${JSON.stringify(error, null, 2)}`));
```

## Draining originated accounts (KT1)

In the following example, we first originate a contract with a starting balance of 8 ꜩ. Then, we transfer all of its tokens to an implicit account.
In the following example, we first originate a contract with a starting balance of 8 ꜩ. Then, we transfer all of its tokens to an implicit account.

The contract we originate is a `manager contract`. It has a `do` method taking a lambda function as a parameter. We call the smart contract by passing a function called `transferImplicit` to its `do` method in order to transfer its tokens to the implicit address. More information on transfers involving originated KT1 addresses can be found [here](https://tezostaquito.io/docs/making_transfers#transfers-involving-originated-kt1-addresses).

In the example, we estimate the transfer operation before doing it. When draining the account, the associated fees will be deducted from the manager's address. Thus, for the operation to be successful, the manager's address for that account must contain funds to cover the gas.
In the example, we estimate the transfer operation before doing it. When draining the account, the associated fees will be deducted from the manager's address. Thus, for the operation to be successful, the manager's address for that account must contain funds to cover the gas.

```js live noInline
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/carthagenet');

function transferImplicit (key, mutez) {
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' },
];
};

Tezos.signer.publicKeyHash()
.then( address => {
Tezos.contract.originate({
balance: "8",
code: managerCode,
init: { "string": address }
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/delphinet');

function transferImplicit(key, mutez) {
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' },
];
}

Tezos.signer
.publicKeyHash()
.then((address) => {
Tezos.contract
.originate({
balance: '8',
code: managerCode,
init: { string: address },
})
.then((contractOrigination) => {
println(
`Waiting for confirmation of origination for ${contractOrigination.contractAddress}...`
);
return contractOrigination.contract();
})
.then((contract) => {
println(`Origination completed.`);
Tezos.tz.getBalance(contract.address).then((balance) => {
println(`The balance of the contract is ${balance.toNumber() / 1000000} ꜩ.`);
const estimateOp = contract.methods
.do(transferImplicit('tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr', balance.toNumber()))
.toTransferParams({});
println(`Waiting for the estimation of the smart contract call...`);
Tezos.estimate
.transfer(estimateOp)
.then((estimate) => {
//Will be deducted from manager's address
println(
`The estimated fees related to the emptying operation are ${estimate.suggestedFeeMutez} mutez.`
);
return contract.methods
.do(transferImplicit('tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr', balance.toNumber()))
.send({ amount: 0 });
})
.then((operation) => {
println(`Waiting for confirmation of the draining operation...`);
return operation.confirmation(1).then(() => operation.hash);
})
.then((hash) => {
println(`The account has been emptied.`);
return Tezos.tz.getBalance(contract.address);
})
.then((finalBalance) => {
println(`The balance is now ${finalBalance.toNumber() / 1000000} ꜩ.`);
});
});
});
})
.then( contractOrigination => {
println(`Waiting for confirmation of origination for ${contractOrigination.contractAddress}...`)
return contractOrigination.contract()
}).then ( contract => {
println(`Origination completed.`);
Tezos.tz.getBalance(contract.address)
.then(balance => {
println(`The balance of the contract is ${balance.toNumber() / 1000000} ꜩ.`)
const estimateOp = contract.methods.do(transferImplicit("tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr", balance.toNumber())).toTransferParams({})
println(`Waiting for the estimation of the smart contract call...`);
Tezos.estimate.transfer(estimateOp)
.then( estimate => {
//Will be deducted from manager's address
println(`The estimated fees related to the emptying operation are ${estimate.suggestedFeeMutez} mutez.`)
return contract.methods.do(transferImplicit("tz1PgQt52JMirBUhhkq1eanX8hVd1Fsg71Lr", balance.toNumber())).send({ amount: 0 })
}).then( operation => {
println(`Waiting for confirmation of the draining operation...`);
return operation.confirmation(1).then(() => operation.hash);
}).then(hash => {
println(`The account has been emptied.`)
return Tezos.tz.getBalance(contract.address)
}).then( finalBalance => {
println(`The balance is now ${finalBalance.toNumber() / 1000000} ꜩ.`)
})})})}).catch(error => println(`Error: ${JSON.stringify(error, null, 2)}`));
```
.catch((error) => println(`Error: ${JSON.stringify(error, null, 2)}`));
```
45 changes: 24 additions & 21 deletions docs/estimate.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ The following example shows an estimate of the fees associated with transferring

```js live noInline
// import { TezosToolkit } from '@taquito/taquito';
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/carthagenet');
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/delphinet');

const amount = 2;
const address = 'tz1h3rQ8wBxFd8L9B3d7Jhaawu6Z568XU3xY';

println(`Estimating the transfer of ${amount} ꜩ to ${address} : `);
Tezos.estimate.transfer({ to: address, amount: amount })
.then(est => {
Tezos.estimate
.transfer({ to: address, amount: amount })
.then((est) => {
println(`burnFeeMutez : ${est.burnFeeMutez},
gasLimit : ${est.gasLimit},
minimalFeeMutez : ${est.minimalFeeMutez},
Expand All @@ -43,7 +44,7 @@ Tezos.estimate.transfer({ to: address, amount: amount })
totalCost : ${est.totalCost},
usingBaseFeeMutez : ${est.usingBaseFeeMutez}`);
})
.catch(error => console.table(`Error: ${JSON.stringify(error, null, 2)}`));
.catch((error) => console.table(`Error: ${JSON.stringify(error, null, 2)}`));
```

### Estimate a smart contract call
Expand All @@ -52,28 +53,29 @@ This example will demonstrate how to estimate the fees related to calling a smar

```js live noInline
// import { TezosToolkit } from '@taquito/taquito';
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/carthagenet');
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/delphinet');

Tezos.contract.at('KT1JVErLYTgtY8uGGZ4mso2npTSxqVLDRVbC')
.then(contract => {
Tezos.contract
.at('KT1JVErLYTgtY8uGGZ4mso2npTSxqVLDRVbC')
.then((contract) => {
const i = 7;

return contract.methods.increment(i).toTransferParams({});
})
.then(op => {
.then((op) => {
println(`Estimating the smart contract call : `);
return Tezos.estimate.transfer(op)
return Tezos.estimate.transfer(op);
})
.then(est => {
.then((est) => {
println(`burnFeeMutez : ${est.burnFeeMutez},
gasLimit : ${est.gasLimit},
minimalFeeMutez : ${est.minimalFeeMutez},
storageLimit : ${est.storageLimit},
suggestedFeeMutez : ${est.suggestedFeeMutez},
totalCost : ${est.totalCost},
usingBaseFeeMutez : ${est.usingBaseFeeMutez}`)
})
.catch(error => console.table(`Error: ${JSON.stringify(error, null, 2)}`));
usingBaseFeeMutez : ${est.usingBaseFeeMutez}`);
})
.catch((error) => console.table(`Error: ${JSON.stringify(error, null, 2)}`));
```

### Estimate a contract origination
Expand All @@ -82,25 +84,26 @@ In this example, we will use the estimate method of Taquito on a contract origin

```js live noInline
// import { TezosToolkit } from '@taquito/taquito';
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/carthagenet');
// const Tezos = new TezosToolkit('https://api.tez.ie/rpc/delphinet');

println(`Estimating the contract origination : `);
Tezos.estimate.originate({
Tezos.estimate
.originate({
code: genericMultisigJSONfile,
storage: {
stored_counter: 0,
threshold: 1,
keys: ['edpkuLxx9PQD8fZ45eUzrK3BhfDZJHhBuK4Zi49DcEGANwd2rpX82t']
}
keys: ['edpkuLxx9PQD8fZ45eUzrK3BhfDZJHhBuK4Zi49DcEGANwd2rpX82t'],
},
})
.then (originationOp => {
.then((originationOp) => {
println(`burnFeeMutez : ${originationOp.burnFeeMutez},
gasLimit : ${originationOp.gasLimit},
minimalFeeMutez : ${originationOp.minimalFeeMutez},
storageLimit : ${originationOp.storageLimit},
suggestedFeeMutez : ${originationOp.suggestedFeeMutez},
totalCost : ${originationOp.totalCost},
usingBaseFeeMutez : ${originationOp.usingBaseFeeMutez}`)
})
.catch(error => println(`Error: ${JSON.stringify(error, null, 2)}`));
usingBaseFeeMutez : ${originationOp.usingBaseFeeMutez}`);
})
.catch((error) => println(`Error: ${JSON.stringify(error, null, 2)}`));
```
Loading

0 comments on commit a29809e

Please sign in to comment.