Background introduction

problem mortgaging a part of cfx when sending interaction to the smart contract and returning part of cfx after the interaction when developing smart contracts and deploying them to the Conflux network.

As Roast Boy answered, in the blockchain, a certain amount of storage deposit needs to be charged according to the caller's occupation of the smart contract space. This fee is usually higher than the actual need. When the space is released, it will be returned to the A certain amount of GAS fee for the operator.

Conflux specifically describes this mechanism in detail in its protocol specification

Introduction to Theory

The Collateral for storage (CFS) mechanism was introduced in Conflux as a pricing method for using storage. Compared with the one-time storage fee in Ethereum, the CFS mechanism will be more fair and reasonable. In principle, this mechanism requires locking up a sum of money as collateral for taking up storage space. Before the corresponding storage space is released or covered by others, the collateral will be locked, and the corresponding interest generated by the locked collateral will be directly distributed to miners for the maintenance of storage space. Therefore, the storage cost of Conflux also depends on how long the space is occupied.

In the Conflux network, the space occupied by each storage entry is 64B (B is Bytes, bytes), which is also the size of the key/value pair in the world state. It should be noted that in the blockchain, the key is generally 256bits long, and the value It is also 256bits long (each is 32B long, and together it is 64B long). The deposit required for storage is proportional to the minimum multiple of 64B that can cover all stored items. For each storage entry, the account that last wrote to the entry is called the owner of the storage entry. If a storage entry is written during the execution of contract C, and is guaranteed by a guarantor, then C is regarded as the writer of the entry and accordingly becomes the owner (see Section 7.1 for details). In the world state, the owner of a storage entry must lock a fixed amount of CFX as a storage deposit that takes up storage space for the entire lifetime of the storage entry. Specifically, for each storage entry with a size of 64B, its owner will be locked by 1/16CFX. While occupying 1KB space, 1CFX is paid as a deposit, and the corresponding formula is as follows:

$$\left(\frac{1024}{64}\right)×\left(\frac{1}{16}\right)=1(CFX)$$

When account α becomes the owner of a storage entry (whether created or modified), α shall immediately lock 1/16 CFX for that entry. If α has sufficient balance, then the required deposit is automatically locked, otherwise if α does not have enough balance, the operation fails and α cannot create or modify the entry.

When a storage entry is removed from the world state, the corresponding 1/16 CFX deposit will be unlocked and returned to the entry's owner's balance. If the ownership of a storage entry changes, the old owner's 1/16 CFX deposit is unlocked, while the new owner must lock 1/16 CFX as a deposit at the same time.

To facilitate processing, the function CFS is introduced in Conflux, which takes an account address α and a world state σ as input, and returns the total amount of locked deposit stored by account α in the world state σ. If the world state σ is clear from the context, for brevity, we replace CFS(α;σ) with CFS(α), which is formulated as:

$$CFS(α)≡CFS(α;σ)≡Total number of storage entries owned by account a in world state σ×\left(\frac{1}{16}\right)(CFX)$$

In particular, for a transaction T sent by α=S(T) (or α=T α if T calls α ), let σ be the state of the world before and after T is executed, [sigma] ' state of the world after the end of the transaction execution, for restricted storage field T L a CFS ([alpha]; [sigma]) ≤CFS ([alpha]; [sigma]) + T L / 10 18 is assertion .

Key point: If you want to know how many CFX are pledged by calling the contract, you must know the number of entries in the variable in the contract, and how many entries are modified when the contract is called through the function, and the number of changes is recorded in the block chain!

Solidity memory management mechanism

According to Solidity document description of and Conflux storage deposit mechanism , we can find that contract storage needs to be maintained by key and value. In general, the length of the key is 256bits, and the length of the value is also 256bits. The storage space of a smart contract is organized according to the following table, where {0,1} 256 represents a 256-bit bit string (there are only two values 0 or 1 in the bit string), and each key/value pair of interpreted as an entry :

entrykey/address({0,1} 256 )value({0,1} 256 )
10...000000
20...000011
30...000022
.........
2256f...fffff0

Since 256bits=32bytes, the corresponding length of two 256bits is:
$$32+32=64(Bytes)$$

Common variables in Solidity and their corresponding number of entries

variablelengthHow to define
Ordinary variables1 common variable corresponds to 1 entryuint public count=0;
mappingEach key of the mapping corresponds to an entrymapping(address => uint) public balances;
arrayEach 1 element of the array corresponds to 1 entry, the array length arr.length is an additional 1 entryuint[5] fixedArr = [1,2,3,4,5]; string productname;
structThe accumulation of the number of entries corresponding to each field in the structstruct Person {uint age;uint stuID;string name;}

Description of Conflux's Storage Deposit Mechanism

In Conflux , the fee to store the deposit is 1 CFX 1024 byte. Since each entry occupies 64 bytes, the deposit fee for each entry is 1/16 CFX. During the execution of each transaction, the newly generated deposit fee will be charged uniformly at the end of the transaction execution. If a deposit entry is overwritten by someone else, the overwrite person will pay the deposit deposit, and the original deposit payer will get the deposit back. It is worth mentioning that the deposit refund is "quietly" added to the balance, and there is no transfer transaction available for inquiry.

each transaction of 161e8d741ddd1f Conflux, you need to fill in a storage limit (in bytes). The upper limit stipulates that the deposit increment of the deposit payer shall not exceed the storage upper limit multiplied by 1/1024 CFX before and after the transaction is executed. If this value is filled in too low, the deposit will exceed the upper limit after execution, and the execution will fail. If the filling is too high, the sender's balance is not enough to pay the deposit, and the transaction will also fail.

deploy contract

Please refer to link to try to deploy and invoke the smart contract.

Example explanation

1. An example with 1 normal uint variable

The smart contract code is as follows:

pragma solidity ^0.5.0;

contract Counter {
    uint public count=0;
    event SelfEvent(address indexed sender, uint current);

    constructor() public {
    }

    function inc(uint num) public returns (uint){
        return count += num;
    }

    function self() public {
        emit SelfEvent(msg.sender, count);
    }
}

Since there is only uint public count=0; the smart contract, it only corresponds to 1 entries, according to the previous formula analysis:
$$CFS(α)≡CFS(α;σ)≡Total number of storage entries owned by account a in world state σ×\left(\frac{1}{16}\right)(CFX)$$

It is precisely because the uint public count=0 variable corresponds to a 64B entry, combined with the example we gave before, the real pledge amount is: 0.0625 CFX
$$\left(\frac{1}{16}\right)=0.0625(CFX)$$

The following is combined with the actual call to the contract to verify:
The case of calling the contract code is as follows (file name: call_calc.js):

const { Conflux, util } = require('js-conflux-sdk');
// 这个地址是上面打印出来的 receipt.contractCreated 
const public_address = '0x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca';
const contractAddress = '0x845dd6f64bb3d2771a8f30dc85bb14f5ac26b75e';
const PRIVATE_KEY1 = '0x2772b19636f1d183a9a2a0d27da2a1d0efb97637b425********************';
const PRIVATE_KEY2 = '0x2adba218d5eacb5bc9bbb4c6fdecef7d1719c8184812********************';
const compiled = require(`./build/Counter.json`)
async function main() {
  const cfx = new Conflux({
    url: 'http://main.confluxrpc.org',
  });
  const contract = cfx.Contract({
    address : contractAddress,
    abi: compiled.abi,
  });
  
  const before_call_balance = await cfx.getBalance(public_address);
  console.log("before account1 call the current drip:"+before_call_balance.toString());
  console.log("before account1 call the current cfx:"+util.unit.fromDripToCFX(before_call_balance));
  
  let inc = await contract.inc(10);
  console.log("输出:"  + inc.toString());
  
  const account1 = cfx.Account(PRIVATE_KEY1);//使用私钥创建账户
  
  // 进行记录并花费CFX
  await contract.inc(10).sendTransaction({ from: account1 }).confirmed();
  
  const after_call_balance = await cfx.getBalance(public_address);
  console.log("after account1 call inc(10) the current drip:"+after_call_balance.toString());
  console.log("after account1 call inc(10) the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
    
  //创建account2,并尝试调用合约希望释放account1的cfx
  const account2 = cfx.Account(PRIVATE_KEY2);//使用私钥创建账户
  
  const before_account2_call_balance = await cfx.getBalance(public_address);
  console.log("before account2 call inc(5) the current drip:"+after_call_balance.toString());
  console.log("before account2 call inc(5) the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
  await contract.inc(5).sendTransaction({ from: account2 }).confirmed();
  
  const after_account2_call_balance = await cfx.getBalance(public_address);
  console.log("after account2 call inc(10) the current drip:"+after_account2_call_balance.toString());
  console.log("after account2 call inc(10) the current cfx:"+util.unit.fromDripToCFX(after_account2_call_balance));
  
  
}
main().catch(e => console.error(e));

The calling method is:

node call_calc.js

For the convenience of description, the accounts participating in the calling contract are represented by account1 and account2, and the called contract is represented by contract, and its account information and corresponding account addresses are summarized. The table is as follows:

account nameAccount address
account10x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca
account20x1941E3137aDDf02514cBFeC292710463d41e8196
countract0x845dd6f64bb3d2771a8f30dc85bb14f5ac26b75e

is for convenience, and the account name in the above table is used to refer to each account

Before calling, use confluxscan check the CFX balance corresponding to account1, and find that the balance is: 1994.680912261955354268 CFX.

confluxscan1

(1) Use account1 to make the first contract call:

call

Because account1 calls the contract occupied space , need to hand in CFX as deposit

After the program starts: first display the account balance of account1: 1994.680912261955383167 CFX.

The program will use account1 to call contract.inc(10) to initiate interaction with the contract. After the call is completed, it will be found that the account balance of account1 will become: 1994.618412261955356217 CFX.

sub_call1

That is to say, after this interaction between account1 and contract contract, its account is deducted:
$$1994.680912261955383167-1994.618412261955356217=0.06250000000002695(CFX)‬$$

This shows that the interaction with the contract is due to the call to contract.inc(10). account1 submitted CFX 0.06250000000002695

uses account2 to call contract to help account1 free space

The program will continue to run and use account2 to initiate interaction with the contract by calling contract.inc(5)

Before the call, the account balance of account1 is: 1994.618412261955356217 CFX, which is consistent with the account balance of account1 at the end of step (1).

After account2 calls the contract, account1's CFX balance becomes : 1994.680912261955356217 CFX

sub_call2

That is to say, after account2 calls the contract, the CFX balance of account1's account changes as follows:
$$1994.618412261955356217-1994.680912261955356217=-0.0625(CFX)‬$$

This means that since the 64Bytes contract space occupied by account1 is released, 0.0625 CFX will be returned to account1's account. According to the payment amount calculated in step (1): 0.06250000000002695 CFX, we can speculate that the actual cost of calling contract.inc(10) by account1 is:
$$0.06250000000002695-0.0625=0.00000000000002695(CFX)$$

Before calling the contract, the CFX balance of account1 displayed by the program is: 1994.618412261955437067 CFX.

After calling the contract, the CFX balance of the corresponding account is: 1994.618412261955410117 CFX.

That is to say, after this interaction with the contract, the account has deducted 0.00000000000002695 CFX, and the calculation formula is as follows:
$$1994.618412261955437067-1994.618412261955410117=0.00000000000002695(CFX)$$

This also indirectly proves that the contract space occupied by the data storage in account1 is one 64Bytes:
$$0.0625×16=1(piece)$$

At this point, we go to confluxscan to check the balance corresponding to account1: 1994.680912261955327318 CFX
confluxscan2
According to the calculation formula:
$$1994.680912261955354268-1994.680912261955327318=0.00000000000002695 (CFX)‬$$
This also proves: when account1 calls contract.inc(10) to interact with the contract, its account actually consumes 0.00000000000002695 CFX

2. An example of a fixed-length array with a length of 5 (and the value of 5 elements is modified when called)

The contract code is as follows:

pragma solidity ^0.5.0;

contract Test {
    uint[5] arr = [1,2,3,4,5];
    event SelfEvent(address indexed sender, uint[5] current,uint length);
    
    function init() public{
        arr[0] = 100;
        arr[1] = 200;   
    }
    
    function getArrayContent() public returns(uint[5] memory){
        return arr;
    }
  
    function getArrayLength() public returns(uint){
        return arr.length;
    }
    
    function increment (uint data) public{
        for(uint i=0;i<arr.length;i++){
            arr[i]+=data;
        }
    }
    
    function getGrade() public returns (uint){
        uint grade = 0 ;
        for(uint i=0;i<arr.length;i++){
            grade += arr[i];
        }
        return grade;
    }
    function self() public {
        emit SelfEvent(msg.sender, arr,arr.length);
    }
}

uint [] arr = [1,2,3,4,5]; , an array of length 5 in the smart contract, the 5 entries, and the array length 5 also corresponds to 1 entries, a total of 6 increment() function will modify each element in the array, but does not change the array length , so analyze it according to the previous formula:
$$CFS(α)≡CFS(α;σ)≡Total number of storage entries owned by account a in world state σ×\left(\frac{1}{16}\right)(CFX)$$

It is precisely because the uint [] arr = [1,2,3,4,5]; array and the length of the array correspond to 6 64B, but because the length of the array has not changed and is written into the blockchain, combined with the example analysis we gave before, the amount of pledge should be: 0.3125 CFX
$$\left(\frac{1}{16}\right)×5=0.3125(CFX)$$

The code to call the contract looks like this:

const { Conflux, util } = require('js-conflux-sdk');
// 这个地址是上面打印出来的 receipt.contractCreated 
const public_address = '0x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca';
const contractAddress = '0x822ebe7eb36cdf159d6d544f6321e1a5c6619dc2';
const PRIVATE_KEY1 = '0x2772b19636f1d183a9a2a0d27da2a1d0efb97637b425*';
const PRIVATE_KEY2 = '0x2adba218d5eacb5bc9bbb4c6fdecef7d1719c8184812*';
const compiled = require(`./build/Test.json`)
async function main() {
  const cfx = new Conflux({
    url: 'http://main.confluxrpc.org',
  });
  const contract = cfx.Contract({
    address : contractAddress,
    abi: compiled.abi,
  });
  
  let inc = await contract.getGrade();
  console.log("output:"  + inc.toString());
  
  const before_call_balance = await cfx.getBalance(public_address);
  console.log("before account1 call the current drip:"+before_call_balance.toString());
  console.log("before account1 call the current cfx:"+util.unit.fromDripToCFX(before_call_balance));
  
  const account1 = cfx.Account(PRIVATE_KEY1);//使用私钥创建账户
  
  // 进行记录并花费CFX
  await contract.increment(1).sendTransaction({ from: account1 }).confirmed();
  
  const after_call_balance = await cfx.getBalance(public_address);
  console.log("after account1 call increment() the current drip:"+after_call_balance.toString());
  console.log("after account1 call increment() the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
    
  //创建account2,并尝试调用合约希望释放account1的cfx
  const account2 = cfx.Account(PRIVATE_KEY2);//使用私钥创建账户
  
  const before_account2_call_balance = await cfx.getBalance(public_address);
  console.log("before account2 call increment() the current drip:"+after_call_balance.toString());
  console.log("before account2 call increment() the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
  await contract.increment(2).sendTransaction({ from: account2 }).confirmed();
  
  const after_account2_call_balance = await cfx.getBalance(public_address);
  console.log("after account2 call increment() the current drip:"+after_account2_call_balance.toString());
  console.log("after account2 call increment() the current cfx:"+util.unit.fromDripToCFX(after_account2_call_balance));
}
main().catch(e => console.error(e));

For the convenience of description, the accounts participating in the calling contract are represented by account1 and account2, and the called contract is represented by contract, and its account information and corresponding account addresses are summarized. The table is as follows:

account nameAccount address
account10x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca
account20x1941E3137aDDf02514cBFeC292710463d41e8196
countract0x822ebe7eb36cdf159d6d544f6321e1a5c6619dc2

is for convenience, and the account name in the above table is used to refer to each account

Before calling, use confluxscan check the CFX balance corresponding to account1, and find that the balance is: 1986.673099761952452902 CFX.

sample2_scan1

(1) Use account1 to make the first contract call:

Because the increment() function called by account1 modifies the records stored in the contract, the storage space is occupied, and the modified data is recorded by the , so it is necessary to hand in CFX as a deposit

After the program starts: first display the account balance of account1: 1986.673099761952481801 CFX.

The program will use account1 to call contract.increment(1) to initiate interaction with the contract. This function will add 1 to each element in the array. After the call is completed, the account balance of account1 will become: 1986.360599761952433413 CFX.

sample2_sub_call1

That is to say, after this interaction between account1 and contract contract, its account is deducted:
$$1986.673099761952481801-1986.360599761952433413=0.312500000000048388(CFX)‬$$

This means that the data is modified and the log is written to the blockchain by interacting with the contract by calling contract.increment(1). account1 submitted the CFX 0.312500000000048388

uses account2 to call contract to help account1 free up space

The program will continue to run and use account2 to initiate interaction with the contract by calling contract.increment(2)

Before the call, the account balance of account1 is: 1986.360599761952433413 CFX, which is consistent with the account balance of account1 at the end of the previous operation.

After account2 calls the contract, the CFX balance of : 1986.673099761952433413 CFX

sub_call2

That is to say, after account2 calls the contract, the CFX balance of account1's account changes as follows:
$$1986.360599761952433413-1986.673099761952433413=-0.3125(CFX)‬$$

This means that 0.3125 CFX will be returned to account1's account due to the release of the 320Bytes contract space occupied by account1 calling the increment function. According to the payment amount calculated in step (1): 0.06250000000002695 CFX, we can speculate that the actual cost of calling contract.increment(1) by account1 is:
$$0.312500000000048388-0.3125=0.000000000000048388(CFX)$$

Before account1 calls the contract in the program, the CFX balance of account1 displayed by the program is: 1986.673099761952481801 CFX.

After account2 calls the contract in the program, the CFX balance of account1 account is: 1986.673099761952433413 CFX.

That is to say, after this interaction with the contract, the account1 account has deducted 0.000000000000048388 CFX, and the calculation formula is as follows:
$$1986.673099761952481801-1986.673099761952433413=0.000000000000048388(CFX)$$

At this point, we go to confluxscan to check the balance corresponding to account1: 1986.673099761952404514 CFX
confluxscan2
w=559&h=159&f=png&s=23450)

According to the calculation formula:
$$1986.673099761952452902-1986.673099761952404514=0.000000000000048388 (CFX)‬$$
This also proves: when account1 calls contract.incement(1) to interact with the contract, its account actually consumes 0.000000000000048388 CFX

3. A string and uint (and modifying uint when calling)

The contract code is as follows:

pragma solidity ^0.5.0;

contract Struct_test {

    struct Animal {
        string name;
        uint age;
    }
    event SelfEvent(address indexed sender,uint current);
    event SelfEvent_string(address indexed sender,string current);
    Animal animal1 = Animal("英短",5);
    Animal animal2 = Animal("美短",5);
    
    
    function getAnimal(uint inc) public{
        animal1.age+=inc;
        animal2.age-=inc;
    }
    function get() public view returns(uint256){
        return animal1.age;
    }
    function self() public {
        emit SelfEvent(msg.sender, animal1.age);
        emit SelfEvent(msg.sender, animal2.age);
        emit SelfEvent_string(msg.sender, animal1.name);
        emit SelfEvent_string(msg.sender, animal2.name);
    }    
}

Since there is a structure variable Animal string name; and uint age; in the smart contract, the string corresponds to the long array, the number of corresponding entries is based on the actual setting, and the uint corresponds to 1 entries. getAnimal() function in the contract age variables of the instantiated animal1 and animal2, and the number of modified entries is 2 , so analyze according to the previous formula:
$$CFS(α)≡CFS(α;σ)≡Total number of storage entries owned by account a in world state σ×\left(\frac{1}{16}\right)(CFX)$$

It is precisely because the animal1.age+=inc; and animal2.age-=inc; 2 entries with a length of 64B, and recorded the changes in the blockchain. Combined with the analysis given before, the amount of pledge should be the age in the changed structure instance element. The variable exactly corresponds to 2 entries of 64B length. Since the name has not been changed, combined with the example analysis we gave before, the pledge amount should be: 0.125 CFX
$$\left(\frac{1}{16}\right)×2=0.125(CFX)$$

The code to call the contract looks like this:

const { Conflux, util } = require('js-conflux-sdk');
// 这个地址是上面打印出来的 receipt.contractCreated 
const public_address = '0x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca';
const contractAddress = '0x84dd09cd48e07426c4ac50a389930c034be6c82a';
const PRIVATE_KEY1 = '0x2772b19636f1d183a9a2a0d27da2a1d0efb97637b425*';
const PRIVATE_KEY2 = '0x2adba218d5eacb5bc9bbb4c6fdecef7d1719c8184812*';
const compiled = require(`./build/Struct_test`)
async function main() {
  const cfx = new Conflux({
    url: 'http://main.confluxrpc.org',
  });
  const contract = cfx.Contract({
    address : contractAddress,
    abi: compiled.abi,
  });
  
  const before_call_balance = await cfx.getBalance(public_address);
  console.log("before account1 call the current drip:"+before_call_balance.toString());
  console.log("before account1 call the current cfx:"+util.unit.fromDripToCFX(before_call_balance));
  
  const account1 = cfx.Account(PRIVATE_KEY1);//使用私钥创建账户
  
  // 进行记录并花费CFX
  await contract.getAnimal(3).sendTransaction({ from: account1 }).confirmed();
  
  const after_call_balance = await cfx.getBalance(public_address);
  console.log("after account1 call getAnimal() the current drip:"+after_call_balance.toString());
  console.log("after account1 call getAnimal() the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
    
  //创建account2,并尝试调用合约希望释放account1的cfx
  const account2 = cfx.Account(PRIVATE_KEY2);//使用私钥创建账户
  
  const before_account2_call_balance = await cfx.getBalance(public_address);
  console.log("before account2 call getAnimal() the current drip:"+after_call_balance.toString());
  console.log("before account2 call getAnimal() the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
  await contract.getAnimal(3).sendTransaction({ from: account2 }).confirmed();
  
  const after_account2_call_balance = await cfx.getBalance(public_address);
  console.log("after account2 call getAnimal() the current drip:"+after_account2_call_balance.toString());
  console.log("after account2 call getAnimal() the current cfx:"+util.unit.fromDripToCFX(after_account2_call_balance));
}
main().catch(e => console.error(e));

For the convenience of description, the accounts participating in the calling contract are represented by account1 and account2, and the called contract is represented by contract, and its account information and corresponding account addresses are summarized. The table is as follows:

account nameAccount address
account10x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca
account20x1941E3137aDDf02514cBFeC292710463d41e8196
countract0x84dd09cd48e07426c4ac50a389930c034be6c82a

is for convenience, the account name in the above table is used to refer to each account

Before calling, use confluxscan check the CFX balance corresponding to account1, and find that the balance is: 1983.472904449450987608 CFX.

sample3_scan1

(1) Use account1 to make the first contract call:

Because the getAnimal() function called by account1 modifies the records stored in the contract, the storage space is occupied, and the modified data is recorded by the , so it is necessary to hand in CFX as a deposit

After the program starts: first display the account balance of account1: 1983.472904449451016507 CFX.

The program will use account1 to call contract.getAnimal(3) to initiate interaction with the contract. This function will add 3 to animal1.age and subtract 3 to animal2.age. After the call is completed, the account balance of account1 will become: 1983.347904449450984359 CFX.

sample3_sub_call1

That is to say, after this interaction between account1 and contract contract, its account is deducted:
$$1983.472904449451016507-1983.347904449450984359=0.125000000000032148(CFX)‬$$

This shows that the data is modified and the log is written to the blockchain by interacting with the contract by calling contract.getAnimal(3). has CFX with a quota of 161e8d741de525 0.125000000000032148 161e8d741de526.

uses account2 to call contract to help account1 free up space

The program calling the contract will continue to run and use account2 to initiate interaction with the contract by calling contract.getAnimal(3)

Before the call, the account balance of account1 is: 1983.347904449450984359 CFX, which is consistent with the account balance of account1 at the end of the previous operation.

After account2 calls the contract, account1's CFX balance becomes : 1983.472904449450984359 CFX

sample3_sub_call2

That is to say, after account2 calls the contract, the CFX balance of account1's account changes as follows:
$$1983.347904449450984359-1983.472904449450984359=-0.125(CFX)‬$$

This means that since account1 calls the getAnimal() function to change and occupy the contract space of 128Bytes, which is released by account2's call to the contract, 0.125 CFX will be returned to account1's account. According to the payment amount calculated in step (1): 0.125000000000032148 CFX, we can speculate that the actual cost of calling contract.getAnimal(3) by account1 is:
$$0.125000000000032148-0.125=0.000000000000032148(CFX)$$

Before account1 calls the contract in the program, the CFX balance of account1 displayed by the program is: 1983.472904449451016507 CFX.

After account2 calls the contract in the program, the CFX balance of account1 account is: 1983.472904449450984359 CFX.

That is to say, after this interaction with the contract, the account1 account has deducted 0.000000000000032148 CFX, and the calculation formula is as follows:
$$1986.673099761952481801-1986.673099761952433413=0.000000000000032148(CFX)$$

At this point, we go to confluxscan to check the balance corresponding to account1: 1983.47290444945095546 CFX

sample3_confluxscan2

According to the calculation formula:
$$1983.472904449450987608-1983.47290444945095546=0.000000000000032148 (CFX)‬$$
This also proves: when account1 calls contract.getAnimal(3) to interact with the contract, its account actually consumes 0.000000000000032148 CFX

4. An example with mapping

The contract code is as follows:

pragma solidity ^0.5.0;

contract mapping_test {
    mapping(address => uint) public balances;
    event SelfEvent(address indexed sender,uint current);
    function update(uint newBalance) public {
        balances[msg.sender] = newBalance;
    }
    function self() public {
        emit SelfEvent(msg.sender, balances[msg.sender]);
    }    
}

mapping structure is used in this contract. Since one of the smart contracts contains mapping(address => uint) balance; , and when the related function is called, the data of the entry corresponding to address 1 entries with a length of 64B, and the changes will be recorded in The blockchain, analyzed in conjunction with the example given earlier, should have pledged 0.0625 CFX.

The calling contract code is as follows:

const { Conflux, util } = require('js-conflux-sdk');
// 这个地址是上面打印出来的 receipt.contractCreated 
const public_address = '0x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca';
const contractAddress = '0x8433f943dd6a4cbf13209b9e8674c08349872ce8';
const PRIVATE_KEY1 = '0x2772b19636f1d183a9a2a0d27da2a1d0efb977';
const PRIVATE_KEY2 = '0x2adba218d5eacb5bc9bbb4c6fdecef7d1719c';
const compiled = require(`./build/mapping_test`)
async function main() {
  const cfx = new Conflux({
    url: 'http://main.confluxrpc.org',
  });
  const contract = cfx.Contract({
    address : contractAddress,
    abi: compiled.abi,
  });
  
  const before_call_balance = await cfx.getBalance(public_address);
  console.log("before account1 call the current drip:"+before_call_balance.toString());
  console.log("before account1 call the current cfx:"+util.unit.fromDripToCFX(before_call_balance));
  
  const account1 = cfx.Account(PRIVATE_KEY1);//使用私钥创建账户
  
  // 进行记录并花费CFX
  await contract.update(3).sendTransaction({ from: account1 }).confirmed();
  
  const after_call_balance = await cfx.getBalance(public_address);
  console.log("after account1 call update() the current drip:"+after_call_balance.toString());
  console.log("after account1 call update() the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
    
  //创建account2,并尝试调用合约希望释放account1的cfx
  const account2 = cfx.Account(PRIVATE_KEY2);//使用私钥创建账户
  
  const before_account2_call_balance = await cfx.getBalance(public_address);
  console.log("before account2 call update() the current drip:"+after_call_balance.toString());
  console.log("before account2 call update() the current cfx:"+util.unit.fromDripToCFX(after_call_balance));
  await contract.update(5).sendTransaction({ from: account2 }).confirmed();
  
  const after_account2_call_balance = await cfx.getBalance(public_address);
  console.log("after account2 call update() the current drip:"+after_account2_call_balance.toString());
  console.log("after account2 call update() the current cfx:"+util.unit.fromDripToCFX(after_account2_call_balance));
  
  
}
main().catch(e => console.error(e));

For the convenience of description, the account participating in the calling contract is represented by account1, and the called contract is represented by contract, and its account information and corresponding account address are summarized. The table is listed as follows:

account nameAccount address
account10x17b38613e633c2b8fb4686a3a62b9b782ac5e0ca
account20x1941E3137aDDf02514cBFeC292710463d41e8196
countract0x8433f943dd6a4cbf13209b9e8674c08349872ce8

is for convenience, and the account name in the above table is used to refer to each account

The output when called is as follows:

After the program starts: first display the account balance of account1: 98.955078124999570464 CFX.

The program will use account1 to call contract.update(5) to initiate interaction with the contract. This function will set a new value for balances[msg.sender]. After the call is completed, it will be found that the account balance of account1 will become: 98.892578124999543647 CFX.

That is to say, after this interaction between account1 and contract contract, its account is deducted:
$$98.955078124999570464-98.892578124999543647=0.062500000000026817(CFX)‬$$

Since the entry for storing the pledge is 1, it is correct to pledge 0.0625 CFX, while calling the contract costs 0.000000000000026817 (CFX)


database:


Conflux中文社区
66 声望18 粉丝

Conflux网址:[链接]