思维之海

——在云端,寻找我的星匙。

北斗UMA专项

北斗计划 - 天枢。A little bit of recordings during the UMA session.

References

Conflux

Conflux课程视频

forum.conflux.fun Conflux Forum,Homework & Resources

Lecture 1 - Introduction Of Blockchain

This part is the same as https://stellarkey.github.io/区块链.

Lecture 2 - Cryptoeconomics 加密经济学

winner takes all

Blockchains and cryptocurrency will generate a new and better internet.

Token 通证

SoV: Store of Value; MoE: Media of Exchange.

NFTs: non-fungible tokens(非同质化通证),代表特定数字资产的特殊通证

DeFi: 一类携带投票权的token

Token Design

3 D’s of Token Design

s of Token Design

Conflux Token Economy 通证经济

The cryptoeconomic goals for Conflux were to:
● Attract users to actively use the network for value add services, and global ventures.
● Remove any barriers to entry for those making meaningful contributions
● Support security, stability, and predictability of the network

Key problem

  • Inefficient On-Chain Storage
    ● Ethereum users pay a one time fee at the time of including the code on chain, but the community bears the cost of keeping the contract in storage - much of the state-tree space on Ethereum is occupied by inactive smart contracts.
  • Wasted Computation
    ● BTC and ETH process blocks strictly one-by-one, creating a winner takes all characteristic for mining these chains, increasing the chance of forks.
  • Low Throughput
    ● Many PoW chains have a low TPS, and not suitable for payments.

Conflux Token (CFX)

Conflux’s unique native token is called CFX which is used for economic value transfers and payments for the cost of usage.

CFX was designed to serve as a:

  • Medium of Exchange (MoE)
  • Store of Value (SoV)
  • A unit of account for blockchain based data
  • Miner Incentives (compensation for processing new blocks)

CFX exists in two forms: Liquid and illiquid.

  • Liquid: they can be immediately transferred/used on Conflux
    Network.
  • Illiquid: Tokens are locked up (via staking) in three different forms:
    1) Staked to earn the user interest
    2) Bonded storage to purchase space on the network
    3) Locked up to purchase votes in network governance

Staking 权益制

Staking for Interest 利息

Conflux Network distributes interest on all tokens at a rate of 4% per year.

Staking for Storage Space 存储

A user who wants to use Conflux Network for smart contract execution needs to place a pre-defined number of tokens into a bonded storage.

Staking for Voting Rights 投票权

Conflux Network’s ecosystem fund in the future will transform into a DAO where Conflux stakeholders vote on operations using voting rights.

To cast a vote, users must lock up their tokens, where the time locked up determines the number of votes. Voting rights awarded according to:

Mining Rewards 挖矿奖励

Miners receive income from three sources:

  • Transaction User Fees: In the long term user fees will make the majority of miner income
  • Block Rewards: In the short term, block rewards will make the majority of miner income.
  • Interest Income: Interest on bonded storage tokens are given to miners.

Economy System

Adjust Miner revenue as function of adoption.

Real application is not living in a vacuum, but a complex and random world. That means we have to introduce some random mechanisms into the model.

Lecture 3 - Fundamental Concepts & Tools

从用户的角度理解区块链。

Resources

Accounts & Transactions 账户和交易

Digital signatures 数字签名

digital signatures are cryptographic tools and algorithms used to prove message authenticity and integrity

  • authenticity(真实性): the sender is who they claim to be
  • integrity(完整性): the message has not been modified

大多数区块链系统使用椭圆曲线密码学,即椭圆曲线数字签名算法ECDSA)。【非对称加密】

Wallets

Your identity is: your private-public keypair

钱包就是一个存储 identity 的容器。

js-conflux-sdk

read and run the full example

js-conflux-sdk documentation

Using the upfront 3 lines to install js-conflux-sdk@1.0.0-alpha.4(注意版本)。

Or if you have installed a WSL like me…

Newer version might have different actions.

1
2
3
4
$ mkdir conflux-playground
$ cd conflux-playground
$ npm install js-conflux-sdk@1.0.0-alpha.4
$ node # enter coding mode

Key & Address - Coding practice

This process is nearly impossible to do it backwards.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// import "js-conflux-sdk"
const util = require('js-conflux-sdk/src/util');

// generate a random private key
const privkey = util.sign.randomPrivateKey();
console.log('private key:', util.format.hex(privkey));

// derive public key from private key
const pubkey = util.sign.privateKeyToPublicKey(privkey);
console.log('public key:', util.format.hex(pubkey));

// derive address from public key
const address = util.sign.publicKeyToAddress(pubkey);
console.log('address:', util.format.hex(address));

sign a message using our private key

1
2
3
4
const Message = require('js-conflux-sdk/src/message');
const msg = new Message("Hello! Sincerely, Vel");
msg.sign(privkey);
console.log('signed message:', msg)

check message authenticity

检查信息是否被修改。

1
2
3
4
// const Message = require('js-conflux-sdk/src/message');
const assert = require('assert');
let recovered = Message.recover(msg.signature, msg.hash)
assert.equal(recovered, util.format.hex(pubkey))

tamper with message

1
2
3
4
console.log('message:', msg.message);
msg.message = "Hello! Sincerely, ----- Hacker";
recovered = Message.recover(msg.signature, msg.hash)
assert.notEqual(recovered, util.format.hex(pubkey))

full example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
const Account = require('js-conflux-sdk/src/account');
const assert = require('assert');
const { Conflux, Drip, Message, util } = require('js-conflux-sdk');

async function main() {
// ---- generate random private key ----
const privkey = util.sign.randomPrivateKey();
console.log('private key:', util.format.hex(privkey));

// ---- derive public key ----
const pubkey = util.sign.privateKeyToPublicKey(privkey);
console.log('public key:', util.format.hex(pubkey));

// ---- derive address ----
const address = util.sign.publicKeyToAddress(pubkey);
console.log('address:', util.format.hex(address));

// ---- sign message ----
const msg = new Message('Hello! Sincerely, Peter');
msg.sign(privkey);
console.log('signed message:', msg)

// ---- check signature ----
let recovered = Message.recover(msg.signature, msg.hash)
assert.strictEqual(recovered, util.format.hex(pubkey))

// ---- detect tampering using signature ----
msg.message = 'Hello! Sincerely, ----- Hacker';
recovered = Message.recover(msg.signature, msg.hash)
assert.notStrictEqual(recovered, util.format.hex(pubkey))

// ---- create and sign transaction ----
const local_account = new Account({ privateKey: util.format.hex(privkey) });

const tx = local_account.signTransaction({
from: util.format.hex(address),
to: util.format.hex(address),
value: Drip.fromCFX(10).toDrip(),
nonce: '0x00',
gasPrice: '0x00',
gas: '0x00',
storageLimit: '0x00',
epochHeight: '0x00',
});

console.log('transaction:', tx);
console.log('transaction hash:', tx.hash);

// ---- send transaction ----
const conflux = new Conflux({ url: 'http://mainnet-jsonrpc.conflux-chain.org:12537' });

// TODO: import your Conflux Portal wallet
// follow: Account Details, Export Private Key
// make sure to add a '0x' prefix to your private key
// make sure your account has sufficient balance
const account = conflux.Account({ privateKey: util.format.hex(privkey) });

// set recipient
const to = '0x145834072064DcD9B931237B5aEe217c241e3644';

// set value to send
const value = Drip.fromCFX(10).toDrip();

const epochHeight = await conflux.getEpochNumber();
const estimate = await conflux.estimateGasAndCollateral({ to, value });
const gasPrice = await conflux.getGasPrice();
const nonce = await conflux.getNextNonce(account.address);
const status = await conflux.getStatus();

const txHash = await account.sendTransaction({
to,
value,
nonce,
gasPrice,
gas: estimate.gasUsed,
storageLimit: estimate.storageCollateralized,
chainId: status.chainId,
data: null,
epochHeight,
});

console.log('sending transaction, hash:', txHash);

// wait 10 seconds
await new Promise(resolve => setTimeout(resolve, 10 * 1000));

// get transaction
const transaction = await conflux.getTransactionByHash(txHash);
console.log('transaction:', transaction);

// wait 10 seconds
await new Promise(resolve => setTimeout(resolve, 10 * 1000));

// get receipt
const receipt = await conflux.getTransactionReceipt(txHash);
console.log('receipt', receipt);
}

main()

Account

▸for each identity, there is a corresponding account maintained on the blockchain
▸the account captures a state at a given time: the current balance, the number of transactions sent, code, …
▸your address will not change (though you might have multiple addresses)
▸the account state associated to your address will change as you send and receive transactions


JSON-representation of a new account:

see: https://developer.conflux-chain.org/docs/conflux-doc/docs/json_rpc/#cfx_getaccount

1
2
3
4
5
6
7
8
9
{
"accumulatedInterestReturn": "0x0",
"admin": "0x0000000000000000000000000000000000000000",
"balance": "0x0",
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82...",
"collateralForStorage": "0x0",
"nonce": "0x0",
"stakingBalance": "0x0"
}

each account has a balance(CFX余额) associated with it.

nonce(交易数): number of accepted transactions from this account

SIMPLE PAYMENT TRANSACTIONS:

  • simply sending a number of coins (tokens) from one address to another
  • the sender signs the transaction using their private key
  • if you do not have my private key, you cannot send on my behalf

Transaction

JSON-representation of a transaction:

1
2
3
4
5
6
7
8
9
10
11
12
{
"from": "0x1dBDA5dD2e952914bC74a802510D0FA59F9d7636",
"to": "0x145834072064DcD9B931237B5aEe217c241e3644",
"value": "0x3635c9adc5dea00000",
"gas": "0x5208",
"gasPrice": "0x174876e800",
"nonce": "0x1",
"data": "0x",
"v": "0x1",
"r": "0x27e5cb110dd198b8fc963d4741ec0840400a6351d9e0c458eed...",
"s": "0x2c486d8e26da3c867fbcf4ab242af1265a5036c5e23ea42c8ab...",
}

from / to: payment transactions specify a sender and a receiver

value: you also need to specify how much you want to send(转账金额)

gas / gasPrice: you might need to pay for transaction(交易费)

nonce: nonce is the number of the transaction(交易号)

data: data is used for smart contract calls(用于智能合约)

SIGNATURE{v, r, s}: a transaction needs to be signed by the sender(签名)

transactions are identified by the transaction hash

1
0x53fe995edeec7d241791ff32635244e94ecfd722c9fe90f34ddf59082d814514

You can do queries like these:
▸ Check if transaction 0x53fe995 succeeded
▸ Find the sender address of transaction 0x53fe995
▸ Get the execution results of transaction 0x53fe995

Distributed ledger 分布式账本

Block 区块

a block is just a list of transactions (block body)
… plus some metadata (block header)

JSON-representation of a block:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"hash": "0xc8f5310402330767adb624f436fa579ca3a6e28bb33f09ec...",
"miner": "0x1905c5723adf66f14f9a33d6d99263cb00c2992c",
"nonce": "0x30176787e0290260",
"parentHash": "0xb11d32edb8e8f09941000c898269f665d275342694...",
"epochNumber": "0x4bad97",
"refereeHashes": [ ... ],
"transactions": [
"0x0b5b3d8f542a3c830ec57b83c07d1282241712478edab3ba8e1a05...",
"0x96b46d10999cda47c4fda1dab7e8e29ce68f5b9ae2d707fde008c7...",
...
],
}

hash: just like txs, blocks are uniquely identified by their hashes

miner & nonce: some information about the creator of the block (see PoW)

parentHash / epochNumber / refereeHashes: information about the blocks position on our ledger

Blockchain

Tree-graph

Conflux uses a Tree-Graph ledger instead of a single chain

… this way, if two blocks are created simultaneously, the system can use both, thus increasing throughput and security

THE LEDGER OF CONFLUX — FURTHER READING

Smart contracts 智能合约

imagine that your mailbox has a machine inside that decides what to do with the coins

moreover, you can also pass it notes with instructions, not just coins

this machine can be unique to each box, built by its owner


JSON-representation of a smart contract transaction:

智能合约的两个特征:

  • to starts with an 8(normal contract starts with a 1
  • data field is not empty(某种方法签名)
1
2
3
4
5
6
7
8
9
10
11
12
{
"from": "0x1dBDA5dD2e952914bC74a802510D0FA59F9d7636",
"to": "0x8b017126d2fede908a86b36b43969f17d25f3770",
"value": "0x3635c9adc5dea00000",
"gas": "0x5208",
"gasPrice": "0x174876e800",
"nonce": "0x1",
"data": "0xa6f2ae3a",
"v": "0x1",
"r": "0x27e5cb110dd198b8fc963d4741ec0840400a6351d9e0c458eed...",
"s": "0x2c486d8e26da3c867fbcf4ab242af1265a5036c5e23ea42c8ab...",
}

transaction receipt 交易收据

JSON-representation of a receipt(收据):

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"from": "0xb2988210c05a43ebd76575f5421ef84b120ebf80",
"to": "0xb2988210c05a43ebd76575f5421ef84b120ebf80",
"transactionHash": "0x53fe995edeec7d241791ff32635244e94ecfd7..."
"epochNumber": 451990,
"blockHash": "0xbb1eea3c8a574dc19f7d8311a2096e23a39f12e649a...",
"index": 0,
"outcomeStatus": 0, // 0 means succeed
"contractCreated": null, // created successfully
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x0000000000000000000000000000000000000000000...",
}

from / to / transactionHash: transaction info

epochNumber / blockHash / index: location on the ledger(对某些应用程序有用)

outcomeStatus / contractCreated / gasUsed / logs / logsBloom: execution results

Inspect data on the ledger

Conflux Scan(Blockchain Explorers)

blockchain explorers are data aggregators that you can use to query accounts, transactions, blocks, etc.

for Conflux, the official blockchain explorer is called Conflux Scanconfluxscan.io

Set up wallet & Send transactions

wallet’s usage

a keypair represents an identity on the blockchain

  • public key / address: your public identity
  • private key: your authorization to act on behalf of this identity

if you know an account’s private key, you can sign transactions from that account

  • storing keys securely is challenging even for experts

  • store private keys, create and sign transactions
  • connect to a blockchain node
  • send transactions into the system
  • monitor transaction and account state

Conflux Portal(Wallet)

Conflux Portal(portal.conflux-chain.org) is the wallet we will use for this course

it is a browser extension(浏览器扩展) available for all major browsers

it allows you to send simple transactions or even interact with smart contracts and dapps

Conflux Portal is based on MetaMask (Ethereum)

Create a wallet

  • first, we need to install the extension
  • during onboarding, we can choose whether we want to import and existing wallet or create a new one
  • the wallet will generate a private key and store it encrypted using a password you choose
  • instead of a hex string, you’ll see the private key as a mnemonic phrase — 12 English words

我们可以通过“存入”(Deposit)按钮来获取一些没有任何价值的免费代币。

完成后,截取message的tx字段(交易哈希值),将可以在Conflux Scan上搜索到相应的交易:

执行一笔转账交易:

Wallet Security 101

  • remember: if you lose your private key (seed phrase), no one will be able to recover your funds
  • remember: if someone gains access to your private key, they can (and will) steal your funds
  • best to backup seed phrase on a piece of paper or using a password manager
  • for higher security, use a hardware wallet

How to acquire tokens?

▸ get free test CFX on testnet or Oceanus through faucet

▸ earn CFX through mining (mining.confluxnetwork.org)

▸ earn FC through bounty (bounty.conflux-chain.org)

▸ earn FC through grants (grants.confluxnetwork.org)

▸ buy FC on moondex.io or other exchanges(if you have another digital currency like bitcoin)

Interactive map of Conflux nodes (confluxmap.com 5)

Interact with dapps(去中心化应用)

Demo:http://167.172.160.61

查询相应的智能合约交易记录:

Homework of Lecture 3

Lecture 3 - Homework & Resources

Homework is done by a group.

transaction classification

1)On which network is this transaction? 0xb97e091e42252571072ae9c605bda16c8f2568cb6a4ff8fd717d384123074b55

Conflux now have a test network(Conflux Testnet) , and a pre-mainnet network(Conflux Oceanus).

But none of those networks have the requested transaction.

2)Find a block with 20 or more transactions and send us the block hash.

0x618f924e1f6c7eab371551d8a5e407aeecd9a192bdd130204dc1ccc42566360f

note: this block is from the Conflux Testnet,and contains 280 transactions.

And there is a JS code to automatically find a block with 20 or more transactions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const { Conflux } = require('js-conflux-sdk');

async function main() {
// initalize a Conflux object
const cfx = new Conflux({
url: 'http://mainnet-jsonrpc.conflux-chain.org:12537',
defaultGasPrice: 100,
defaultGas: 1000000,
logger: console,
});
let epochStart = 7742635
let answer = false
for(var i = epochStart; i> 0; i--){
const blockArray = await cfx.getBlocksByEpochNumber(i)
for (block in blockArray) {
let result = await cfx.getBlockByHash(blockArray[block])
if (result['transactions'].length >=20 ) {
answer = result['hash']
break
}
}
if (answer) break
}
console.log('result is ' + answer)
}

main();

By running it, we can find the results: 0x273d13668462ae7cbb14f25fea0eb8bdbac2dfcd4571a3c5139f08a864d160ba

note: this block is from the Conflux Oceanus,and contains 22 transactions.

Here is the running test:

failed transaction

3)Try to find a failed transaction. Did the sender retry?

Failed First try:**0x6151cf6ceb0d2156e6f35c258d94e27ebc299d149ee664544db343c8e5d29520**

Failed Second try: 0x7635749799dafce791bb952d7a83859c1c4faca8f6cb3d2652fabb073a992241

Successful Third try:

0x6151cf6ceb0d2156e6f35c258d94e27ebc299d149ee664544db343c8e5d29520

Doing smart contract actually also has failed several transactions…

CFX faucet test

4)Create a wallet, get some CFX through the faucet and send us the corresponding transactions hash.

1
{"code":0,"message":{"tx":"0x0163755fe87b34053d2f949ba757b23f3fdbff47ac73b3b0af3e8fb2cabba2d4"} }

Use “Deposit” button to get free CFX~~

0x0163755fe87b34053d2f949ba757b23f3fdbff47ac73b3b0af3e8fb2cabba2d4

buy a ticket

5)Buy a ticket on 167.172.160.61 and send us the corresponding transaction hash.
5.1)What happens if you lower the gas limit before sending the transaction?
5.2)What happens if you try to buy a second ticket for the same address?

5)0xbc6e65773ce248c40743c4cbad6472284f3b2a2ab9ef6b86e1a2734b049c0248

5.1)there is a minimal gas limit:

When I lower the gas limit, I get a failed transaction: (Out of gas)

5.2)When I try to buy a second ticket for the same address, I get a failed transaction: (Execution error, maybe the smart contract constraints that one address can only buy one ticket)

On the contrary, if I choose to buy a second ticket from another account(address):(first, need unauthorize the website, and reconnect to choose another account)

query ticket purchases

6)Try querying recent ticket purchases. Has there been any?

Yes. Use the Purchase method: (And that "0x1e51d.. address is one of my account)

creator of the Tickets contract

7)Who is the creator of the Tickets contract?

First, use owner method to get an address:

Then search for the address:

This seems not what we want, so I track which account all the tokens are transferred into:

And…search, with two-step validation, I think I’ve found the creator of this contract:

  • most definitely 0x1dbda5dd2e952914bc74a802510d0fa59f9d7636

And I think 0x8B017126d2FEDe908a86B36b43969F17d25F3770 is the address of this contract. But I couldn’t be able to find any source code of the contract using Conflux Scan.

balance of this account

8)What is the balance of this account? How do you think this account acquired these tokens?

The creator’s address 0x1dbda5dd2e952914bc74a802510d0fa59f9d7636:

The contract’s address 0x8b017126d2fede908a86b36b43969f17d25f3770:

  • 330 CFX

    ▸people buy tickets from this address and send it 33 * 10 CFX (which means there are 33 tickets been sold)

the most FC tokens address

9)Which address holds the most FC tokens?

  1. the conflux system address
    1. System is responsible for 1:1 exchange of FC/CFX transactions
      1. In this scenario, the contract creator’s address 0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c might have had the most FC tokens because this address is currently holding an enormous amount of CFX roughly about 999999996999988 CFX. That’s really something.
    2. System delivers FC tokens to all other users
    3. So in theory it should hold the most FC tokens
  2. 0x1878e9b8d2fec316a2e666485b927e92a3b4f43e
    1. This address holds 55999 FC tokens, and was involved in the first FC contract transaction
    2. Considering the total amount of FC tokens is about 4484424 FC tokens, this could also have a great chance to be the address that holds the most FC tokens

Lecture 4 - Introduction to Smart Contracts

Decentralized Applications Architecture

Traditional Web Applications (Web 2.0)

Web 2.0 uses the C/S model.

  • Enter domian, retrieve frontend through HTTP(S)
  • User interacts with the frontend which might send additional requests to the backend (dynamic content)
  • The backend could be a server cluster or a cloud, but the main logic remains the same

Decentalized Applications (Web 3.0)

Web 3.0 uses the P2P model (partly):

  • Get frontend from server
  • Frontend initiates transaction
  • User approves transaction
  • There might still be dynamic content
  • Backend can also query the blockchain

IPFS(星际文件系统):一个去中心化的文件存储系统。

Conflux Studio Overview

a 3rd-party IDE called Conflux Studio

Toolchain

we will use these tools
▸ Conflux Studio (v0.4.1) https://github.com/ObsidianLabs/ConfluxStudio/blob/master/README.md
▸ Docker (latest) https://www.docker.com/products/docker-desktop
▸ Solidity 7.1, solc (v0.7.1)
▸ Conflux Truffle (v.0.0.8)
▸ conflux-rust (v.0.6.3

Basic Usage

Docker的原理是在本地运行一个conflux节点,实际上整个网络都在本地,但只包含一个节点,所以非常适合本地开发。

下载课程的智能合约示例:https://github.com/Thegaram/cfx-uma-resources/raw/master/cfx-lecture-4-tickets.zip

在studio中打开上述项目,注意路径名不要有中文。

Writing Smart Contracts

The code that is executed is called EVM bytecode. We write contracts in higher-level languages, the most popular language used on Ethereum and Conflux is Solidity.

为智能合约专门设计的高级语言。

EVM bytecode:Ethereum Virtual Machine bytcode 以太坊虚拟机字节码

CVM:Conflux Virtual Machine(和EVM基本一致,智能合约的编写是兼容的)

example.sol :

1
2
3
4
5
6
7
8
9
10
11
12
13
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.1;

contract ContractName {
uint256 number;
address owner;
mapping (address => uint256) counts; // 字典

function foo(uint256 value) public {
counts[owner] = value;
}
}

abi.json :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[
{
"name": "foo",
"type": "function"
"inputs": [
{
"internalType": "uint256",
"name": "val",
"type": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable",
}
]

Tockets.sol

讲了讲怎么使用。。


introduction to dapps
ethereum.org/en/developers/docs/dapps

built on Ethereum — dapp examples
docs.ethhub.io/built-on-ethereum/built-on-ethereum

official Solidity 7.1 documentation
solidity.readthedocs.io/en/v0.7.1

learn X in Y minutes (where X=Solidity) warning! earlier Solidity version
learnxinyminutes.com/docs/solidity

Solidity by example warning! earlier Solidity version
solidity-by-example.org/0.6

CryptoZombies
cryptozombies.io


Conflux Studio overview
github.com/ObsidianLabs/ConfluxStudio/blob/master/README.md

dapp tutorial
github.com/ObsidianLabs/conflux-dapp-tutorial

Conflux frontend example project
github.com/ObsidianLabs/conflux-frontend-react


Solidity Security: Comprehensive list of known attack vectors and common anti-patterns
blog.sigmaprime.io/solidity-security.html
github.com/zxhubo/Knowledge-Base

the Ethernaut (by OpenZeppelin)
ethernaut.openzeppelin.com

Homework of Lecture 4

Lecture 4 - Homework & Resources

Homework is done by a group.

Conflux Studio

3.1 Basic usage of Conflux Studio

Download and install Conflux Studio and all the components required.

Done.

Download the Tickets project from the lecture (https://github.com/Thegaram/cfx-uma-resources/raw/master/cfx-lecture-4-tickets.zip) and import it into Conflux Studio.

Done.

Deploy an instance of the contract on Conflux Oceanus (hint: you can send CFX from your Conflux Portal account to your Conflux Studio account).

get CFX from faucet: wallet.confluxscan.io/faucet/dev/ask?address={address}

To make sure the deploying account has enough CFXs to pay transaction fees.

Or (send CFX from your Conflux Portal account to your Conflux Studio account)

And Deploy~

Buy a ticket from another account. Validate the ticket with the owner. Withdraw the profits.

First, find the contract we deployed, which leads us to the contract method’s panal:

s panal

And we just buy, validate, and withdraw.

Send us the address of the contract, the 4 transaction hashes (deploy, buy(), validate(), withdraw()), and screenshots of how you sent them from Conflux Studio.

deploy: 0x1c5d87cbc299df5f2d5f07d989e2df83ebca253838edb0836b86d24587b72878

buy: 0xcfbdf3ae39291ea42c85142e18514d4d7329a88057fa8811f043a7869619bcb6

validate: 0xe4e4dbbc708a7e5e5272e8323d124052297ed4dd6ae772da8b2bc9a416b0f2d7

withdraw: 0x367034b42d8cce63f19cf585b3644587e084f8456fd3a562f223dfdd7341c3f9

Tickets.sol

3.2 Customizing Tickets.sol

Update Ticket.sol so that it becomes possible to set the number of tickets and the price per ticket when you deploy a contract.

For instance, for event A, I want to sell 10 tickets of 100 CFX each. For event B, I want to sell 1000 tickets for 2 CFX each.

Test your solution on a local development network.

Send us the source code and a screenshot of deploying a contract with 33 tickets for 44 CFX each.

Just set a few constructor’s parameters and all is OK.

1
2
3
4
5
constructor(uint256 tickets, uint256 price) {
owner = msg.sender;
num_tickets = tickets;
price_drips = price * 1e18;
}

Then we get a panal with adjustable number of tickets and price for each.

Send the transaction, and check:

Buy tickets

+1. Buying multiple tickets from one address [OPTIONAL]

Update Tickets.sol so that one user can buy multiple tickets. For instance, Bob might want to buy 2 tickets, one for himself and one for his girlfriend.

Test your solution on a local development network.

Send us the source code and some screenshots of buying 2 or more tickets from an address and then validating them.

Source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.1;

contract Tickets {
address public owner;

uint256 public num_tickets = 100;
uint256 public price_drips = 10 * 1e18; // 10 CFX
mapping (address => uint256) public has_ticket;

event Validated(address visitor, uint256 tickets);

constructor(uint256 tickets, uint256 price) {
owner = msg.sender;
num_tickets = tickets;
price_drips = price * 1e18;
}

// buy ticket
function buy(uint256 tickets) public payable {
// check tickets
require(num_tickets > 0 && tickets <= num_tickets && tickets > 0, "TICKETS: illegal operation");

// check if the buying price is correct
require(msg.value == tickets * price_drips, "TICKETS: incorrect amount");

// successful buy
if( has_ticket[msg.sender] != 0 )
has_ticket[msg.sender] += tickets;
else
has_ticket[msg.sender] = tickets;
num_tickets -= tickets;
}

// validate ticket
function validate(address visitor) public {
require(msg.sender == owner, "TICKETS: unauthorized");
require(has_ticket[visitor] > 0, "TICKETS: visitor has no ticket");

uint256 tickets = has_ticket[visitor];
has_ticket[visitor] = 0;
emit Validated(visitor, tickets);
}

// withdraw profit
function withdraw() public {
require(msg.sender == owner, "TICKETS: unauthorized");
uint256 profit = address(this).balance;
msg.sender.transfer(profit);
}
}

We set tickets_num to 2333, and price to 1 CFX. (And buy 5 tickets.)

buying 2 or more tickets from an address:

validating them:

Time of the event

+1. Time of the event [OPTIONAL]

Update Tickets.sol so that the organizer can set the time of the event.

Allow users to buy tickets up to 2 hours before the event. E.g. if the event is on 2020.12.01 19:00, you cannot buy tickets after 2020.12.01 17:00.

Allow the organizer to withdraw the profits 1 day after the event. E.g. if the event is on 2020.12.01 19:00, the organizer cannot withdraw the profits before 2020.12.02 19:00.

Hints:

Source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.7.1;

contract Tickets {
address public owner;

uint256 public num_tickets = 100;
uint256 public price_drips = 10 * 1e18; // 10 CFX
uint256 public start;
mapping (address => uint256) public has_ticket;

event Validated(address visitor, uint256 tickets);

constructor(uint256 tickets, uint256 price, uint256 upcoming_days_of_the_event) {
owner = msg.sender;
num_tickets = tickets;
price_drips = price * 1e18;
start = upcoming_days_of_the_event * 1 days + block.timestamp;
}

// buy ticket
function buy(uint256 tickets) public payable {
// check time
require(block.timestamp <= start - 2 hours, "TICKETS: can't but due to time reasons");

// check tickets
require(num_tickets > 0 && tickets <= num_tickets && tickets > 0, "TICKETS: illegal operation");

// check if the buying price is correct
require(msg.value == tickets * price_drips, "TICKETS: incorrect amount");

// successful buy
if( has_ticket[msg.sender] != 0 )
has_ticket[msg.sender] += tickets;
else
has_ticket[msg.sender] = tickets;
num_tickets -= tickets;
}

// validate ticket
function validate(address visitor) public {
require(msg.sender == owner, "TICKETS: unauthorized");
require(has_ticket[visitor] > 0, "TICKETS: visitor has no ticket");

uint256 tickets = has_ticket[visitor];
has_ticket[visitor] = 0;
emit Validated(visitor, tickets);
}

// withdraw profit
function withdraw() public {
require(msg.sender == owner, "TICKETS: unauthorized");

require(block.timestamp >= start + 1 days, "TICKETS: can't withdraw due to time reasons");

uint256 profit = address(this).balance;
msg.sender.transfer(profit);
}
}

Set the start time as 3 days later:

Let’s buy some tickets and test if we can withdraw the money ahead of schdule:

Now we can see:

Transaction reverted

data TICKETS: can’t withdraw due to time reasons

Lecture 5 - Introduction to Smart Contracts II

No slides, only demos.

minting / burning logic

minting即铸币,burning即销毁。这部分的逻辑控制代币的产生和消失。

minting ~ token issuance(发行):

  • fixed-supply token
  • set of addresses to mint, e.g. stablecoin
    • 管理者有权超发货币
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity ^0.7.1;

import "./IStandardCoin.sol";

contract CourseCoin is IStandardCoin { // inheritance / implementing an interface
string _name;
string _symbol; // ~ CFX
uint256 _totalSupply;

// keep track of account balances
mapping (address => uint256) _balances;

event Transfer(address from, address to, uint256 amount);

constructor(uint256 totalSupply) {
_name = "Conflux UMA Token";
_symbol = "UMA";
_totalSupply = totalSupply;

// add all tokens to creator
_balances[msg.sender] = totalSupply;
}

// getters
function name() external view returns (string memory) {
return _name;
}

function symbol() external view returns (string memory) {
return _symbol;
}

function balanceOf(address addr) external view override returns (uint256) {
return _balances[addr];
}

function totalSupply() external view override returns (uint256) {
return _totalSupply;
}

// transfer between accounts
function transfer(address receiver, uint256 amount) external override {
require(_balances[msg.sender] >= amount, "CourseCoin: Insufficient balance");
_balances[msg.sender] -= amount;
_balances[receiver] += amount;
emit Transfer(msg.sender, receiver, amount);
}
}

TimeLockedTransfer

转账交易执行后,receiver只能在截至时间以后才能提取代币。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity ^0.7.1;

import "./IStandardCoin.sol";

contract TimeLockedTransfer {
address _sender;
address _receiver;
uint256 _unlockAfter; // point in time

event CFXDeposit(uint256 amount);
event CFXWithdraw(uint256 amount);
event CoinDeposit(uint256 amount);
event CoinWithdraw(uint256 amount);

constructor(address sender, address receiver, uint256 lockTimeSec) {
_sender = sender;
_receiver = receiver;

// current time: `block.timestamp` (`now` in older versions)
_unlockAfter = block.timestamp + lockTimeSec;
}

function balance() external view returns (uint256) {
return address(this).balance;
}

function depositCFX() external payable {
require(msg.sender == _sender, "TLT: Unauthorized");
uint256 amount = msg.value;
emit CFXDeposit(amount);
}

function withdrawCFX() external {
require(msg.sender == _receiver, "TLT: Unauthorized");
require(block.timestamp >= _unlockAfter, "TLT: Timelock still active");
uint256 amount = address(this).balance;
msg.sender.transfer(amount);
emit CFXWithdraw(amount);
}

//function depositCoin(address coinContract) external payable {
// require(msg.sender == _sender, "TLT: Unauthorized");
//
// IStandardCoin coin = IStandardCoin(coinContract);
// uint256 amount = msg.value;
// coin.transfer(address(this), amount);
// emit CoinDeposit(amount);
//}

function withdrawCoin(address coinContract) external {
// Alice will deposit coins to this contract through the contract
// Bob can withdraw after the deadline by passing the coin contract address
require(msg.sender == _receiver, "TLT: Unauthorized");
require(block.timestamp >= _unlockAfter, "TLT: Timelock still active");

IStandardCoin coin = IStandardCoin(coinContract);
uint256 amount = coin.balanceOf(address(this));
coin.transfer(_receiver, amount);
emit CoinWithdraw(amount);
}
}

Homework of Lecture 5

Lecture 5 - Homework & Resources

Homework is done by a group.

3.1 Understanding the lecture

1.a) Describe some advantages of conforming to a token standard like ERC-20 or IStandardToken in a few sentences.

Conforming to a token standard ensures interoperability between our token and other tokens in the token standard network. This makes buying and trading our tokens easier for end users as well as investors, increasing the appeal of our token.

We can also benefit from unified efforts at improving the security of our token standard. The more networks that share the same token standard, the more stakeholders concerned with the token security, the more research is done to improve the token standard security.

1.b) Describe the purpose of the TimeLockedTransfer contract in a few sentences.

The TimeLockedTransfer contract allows us to set a time for the contract execution. This means that even if all conditions are already fulfilled by a certain time, the contract will not, or cannot, be executed until the prescribed time arrives.It can be used for scheduled transfers or limiting contract accessibility.

If one can not withdraw his profit immediately, one might wanna make sure that his customers won’t come back asking for a refund, which allows the sender to cancel the transfer before the specified deadline.

3.2 Trying the lecture code

Download the project (github.com/Thegaram/cfx-uma-resources/raw/master/cfx-lecture-5.zip 15) and import it into Conflux Studio.

In this problem, you will have to deploy three smart contracts on your local development network.

First, deploy a fixed-supply standard coin with the name “CoinA”. Then, deploy a second instance with the name “CoinB”.

CoinA: 0x8ad093411fb99e82d35c6adfe494821e3d478a70

CoinB: 0x824eebd198b057a4638842247b0a788e8888ef49

Next, deploy an instance of the TimeLockedTransfer contract. Set the unlock time to something greater than 5 minutes.

TimeLockedTransfer: (time = 301 s > 5 min)

Send 17 CFX, 22 CoinA, and 12 CoinB to the transfer contract.

Send 17 CFX:

Send 22 CoinA: (Through contract “CoinA”)

send it to the TimeLockedTransfer contract address.

Send 12 CoinB: (Through contract “CoinB”)

After the deadline, withdraw all these tokens from the transfer contract.

withdraw CFX:

after:

withdraw CoinA:

withdraw CoinB:

after:

Document the process using screenshots and a short description of each step.

+1. Transfer Factory [OPTIONAL]

Look at the file TransferFactory.sol. Try to understand what it does and explain it using your own words.

Show us how to deploy and use this contract.

It creates and maintains a list of “TimeLockedTransfer” contracts.

Each time the function “create” is called, a new “TimeLockedTransfer” contract is deployed.

Deploy: 0x833791606cc08d5e4f5fd9a2d6953faff6c0c494

Create: (3 times)

And we can see those 3 contract infos: (saved in the list called “transfers”)

BUT these tranfers doesn’t work like I expected, and all the contract addresses are invalid.

+1. Cancel transfer [OPTIONAL]

Modify TimeLockedTransfer.sol in a way that allows the sender to cancel the transfer before the specified deadline.

Provide a way for the sender to re-aquire all their tokens from the transfer contract after cancelling it.

Cancel test:

The main source code is as follows: (including several changes in other files not showing here)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity ^0.7.1;

import "./IStandardCoin.sol";

contract TimeLockedTransfer {
address _sender;
address _receiver;
address [] public contracts;
uint256 _unlockAfter; // point in time

event CFXDeposit(uint256 amount);
event CFXWithdraw(uint256 amount);
event CoinDeposit(uint256 amount);
event CoinWithdraw(uint256 amount);
event Cancel(uint256 number);

constructor(address sender, address receiver, uint256 lockTimeSec) {
_sender = sender;
_receiver = receiver;

// current time: `block.timestamp` (`now` in older versions)
_unlockAfter = block.timestamp + lockTimeSec;
}

function balance() external view returns (uint256) {
return address(this).balance;
}

function depositCFX() external payable {
require(msg.sender == _sender, "TLT: Unauthorized");
uint256 amount = msg.value;
emit CFXDeposit(amount);
}

function withdrawCFX() external {
require(msg.sender == _receiver, "TLT: Unauthorized");
require(block.timestamp >= _unlockAfter, "TLT: Timelock still active");
uint256 amount = address(this).balance;
msg.sender.transfer(amount);
emit CFXWithdraw(amount);
}

function depositCoin(address coinContract) external payable {
require(msg.sender == _sender, "TLT: Unauthorized");

contracts.push(coinContract);

IStandardCoin coin = IStandardCoin(coinContract);
uint256 amount = (uint256)(msg.value / 1000000000000000000);
coin.transfer2(msg.sender, address(this), amount);
emit CoinDeposit(amount);
}

function withdrawCoin(address coinContract) external {
// Alice will deposit coins to this contract through the contract
// Bob can withdraw after the deadline by passing the coin contract address
require(msg.sender == _receiver, "TLT: Unauthorized");
require(block.timestamp >= _unlockAfter, "TLT: Timelock still active");

IStandardCoin coin = IStandardCoin(coinContract);
uint256 amount = coin.balanceOf(address(this));
coin.transfer(msg.sender, amount);
emit CoinWithdraw(amount);
}

function cancel() external{
require(msg.sender == _sender, "TLT: Unauthorized");
require(block.timestamp < _unlockAfter, "TLT: Timelock is no longer active");

// cancel CFX
uint256 amount = address(this).balance;
msg.sender.transfer(amount);

// cancel other coins
for(uint i = 0; i < contracts.length; i = i + 1){
address coinContract = contracts[i];
IStandardCoin coin = IStandardCoin(coinContract);
amount = coin.balanceOf(address(this));
coin.transfer(msg.sender, amount);
}

emit Cancel(amount);
}
}

A more step by step demo:

(1) Deploy it with 10 mins delay:

(2) check the CoinA(2317) and CoinB(1234):

(3) send CFX(11), CoinA(12), CoinB(13):

(4) Check CFX(11), the CoinA(2317 - 12 = 2305) and CoinB(1234 - 13 = 1221):

(5) cancel:

CFX(0), CoinA(2317) and CoinB(1234) again:

Lecture 6 - Gas and Gas Sponsorship

transaction fee 交易费

Bitcoin 比特币

比特币最大的创新在于系统机制的设计(incentive alignment)。

Miner Income 矿工收益

miners make money by:

  • processing transactions (transaction fee)
  • creating blocks (block reward)

如上图,1 coin 作为transaction fee变成了矿工的收入。

Incentive Alignment 激励措施

一个预先定义好的协议:

  • 反向激励:if you deviate from the rules, you will lose money
  • 正向激励:instead of attacking the system, you can earn more moneyby actually participating (as a miner)
    • 理性的参与者,将会接受正向激励

this is the reason a native currency is necessary forpermissionless(无条件的) blockchains like Bitcoin and Conflux

transaction fee as an auction 拍卖

每个区块内只能储存有限笔交易,因此矿工倾向于将交易费出价更高的交易打包进区块里面。

愿意给出的交易费越高,你的交易将会更快地得到处理。

Bitcoin机制中的漏洞

自私采矿(selfish mining),这项技术可让矿工赚的钱超过他本应该拿到的合理回报,从而损害系统的公平性。

区块链依赖于信息的快速广泛传播,但是如果矿工手握某些高额交易费的交易信息,那么他可能倾向于把它留在自己手里,获取这笔更高的手续费。

比特币还会形成一定的集中化系统,因为挖矿奖励太稀有了,大家倾向于聚集到矿池中获得更稳定的回报。这在长期来看对比特币系统是一种不利因素。

Ethereum 以太坊

以太坊和比特币最大的不同在于,引入了智能合约

但是,智能合约的调用消耗是非常不确定的:

  • Execution cost: 运行时间可能达到上百万个循环
  • Storage cost: 可能最大需要额外的上百万的空间消耗

Halting Problem 停机问题

halting problem(停机问题): just by looking at the transaction, you cannot decide if it will ever finish running

  • limit the language so that you cannot even write such code (Bitcoin)
    • this works but might severely limit the types of applications you are able to express
  • run for a fixed duration then terminate (Hyperledger)
    • this might harm determinism: code that timeouts on one machine might terminate on another, any they will be unable to reach consensus
  • terminate after a certain number of steps (a certain amount of computation) has been performed
    • you pay for each computational unit so that miners get properly compensated

Gas

Ethereum: “pay-per-computational-step” model

instead of pricing instructions directly in ETH (the price of which fluctuates), we use another metric: GAS

each EVM instruction has a predefined GAS cost that is independent of the value of ETH

the gas cost of a transaction is the sum of the cost for each instruction executed

source: https://github.com/djrtwo/evm-opcode-gas-costs/blob/master/opcode-gas-costs_EIP-150_revision-1e18248_2017-04-12.csv

Gas Limit

when you send a transaction, you specify a gas limit: the maximum amount of GAS you are willing to spend

  • if the execution reaches this limit before finishing, the transaction is reverted and you pay the corresponding fee
  • if the gas used by the execution is below the limit, the remaining gas is refunded to your account

this basically solves the halting problem: you can write infinite loops but you’ll have to pay for them

Gas Price

when you send a transaction, you specify a gas price: the amount of ETH you’re willing to pay per gas

you are free to choose what gas price to set, similarly to Bitcoin where you can set the transaction fee freely

the miner is free to choose which transactions to include. it is likely to choose transactions with higher gas pric

这里也会变成类似比特币的拍卖系统


Example:

Let’s say you can a transaction with

  • gas limit: 50000
  • gas price: 0.00000008 Ether (80 Gwei)

you will have to make an up-front(预付) payment of

  • 50000 x 0.00000008 = 0.004 ETH

if execution uses 41172 gas, after refund you’ll effectively pay

  • 41172 x 0.00000008 = 0.00329376 ETH

Example Contract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
contract Test {
uint256 num_a = 0;
uint256 num_b = 0;

function increment() public {
num_a += 1;
num_b += 1;

// incrementing is essentially equivalent to:
// uint256 current_value = number;
// uint256 new_value = current_value + 1;
// number = new_value;

// solc compiles it like this:
// SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 DUP1
// PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE

// we will simply treat it like this:
// SLOAD ADD SSTORE SLOAD ADD SSTORE
// gas cost: 2 x (3 + 200 + 5000) = 10406 GAS
}
}

what happens if we provide a gas limit of 5203 GAS? (不足的GAS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
contract Test {
uint256 num_a = 0;
uint256 num_b = 0;

function increment() public {
num_a += 1; // this succeeds
// <- we run out of gas at this point
num_b += 1;

// the whole transaction is reverted
// neither num_a nor num_b is updated
// the sender pays for the executed 5203 GAS
}
}

what happens if we provide a gas limit of 12000 GAS? (足够的GAS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
contract Test {
uint256 num_a = 0;
uint256 num_b = 0;

function increment() public {
num_a += 1; // this succeeds
num_b += 1; // this also succeeds
// we finish the execution

// the whole transaction succeeds
// both num_a and num_b will be updated
// the sender pays for the executed 10406 GAS, 1594 is refunded
}
}



Why call it “GAS”? (Why the gas analogy(类比)?

  • gasoline is what really moves your car, just as it moves the execution of smart contracts
  • your car’s gas consumption is roughly static, while the price of gasoline changes
  • you could try stuffing dollar bills into the fuel tank of your car, but instead you buy gasoline using dollars, and use that to run it

Conflux

Conflux inherited the same fee mechanism from Ethereum, with a few changes:

  • limited gas refund
  • separate payment for execution and storage
  • gas can be sponsored(代付机制)

Limited Gas Refund 有限回偿

the cost of a contract call might change, depending on when you call it. consider the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
contract MaybeExpensive {
uint256 num = 0;
event E(uint8 n);

function increment() public { num += 1; }

function foo() public {
if (num == 0) {
for (uint8 ii = 0; ii < 1000; ii++) {
emit E(ii);
}
}
}
}

triggering foo() might do almost nothing, or it might also emit 1000 events, depending on the current value of num

  • in Conflux, miners cannot know for sure the state on whichthe transaction is executed
    • this makes it impossible to accurately estimate the profits of including certain transactions
  • to make this estimation easier, at most 1/4 of the whole gas is refunded
    • e.g. if gas limit is 10000 and the transaction execution used 6000 gas, the account will still be charged for 7500

这是对矿工收益的权衡之举。

Pay Separately for Storage 存储抵押费

in Ethereum paying for storage is a one-time fee (gas for SSTORE), even though miners might have to store it forever.

consider this example: that 13 has to be stored on each machine maintaining the blockchain.

1
2
3
4
5
6
contract Storage {
mapping (address => uint256) data;
constructor() {
data[msg.sender] = 13;
}
}

in Conflux, you need to deposit CFX for storage entries.
this deposit is called storage collateral.

miners earn interest on the collateralized storage

if someone deletes or overwrites your entry, you get back your collateral




so what you will pay is

(gas_used x gas_price) + (1/16 CFX x storage_collateralized)

… minus the refund of at most 1/4 x gas_used x gas_price

transaction sponsorship

The Problem with Gas

Ethereum dapps: high entry barrier

  • get a wallet, acquire some ETH, …

are people willing to pay for each transaction?

  • web 2.0: you have to pay for your server’s uptime but you don’t directly push this onto your customers; you have other revenue streams

Sponsorship Mechanism in Conflux

某个人可以选择为某个智能合约的所有交易代付手续费。从而降低人们参与智能合约的门槛。

someone can choose to sponsor transactions to a smart contract, i.e. pay on the sender’s behalf

example use case: MoonSwap

  • UniSwap: if you swap ETH for USDT, fees are around $4.1 at the time of writing
  • MoonSwap: would cost $0.4 at current price but in practice it’s $0 because the transaction is sponsored

代付白名单控制

there is a built-in contract(魔术合约,系统内置,由Conflux提供) called SponsorWhitelistControl
address: 0x0888000000000000000000000000000000000001

sponsor calls setSponsorForGas(…) to become the sponsor of a smart contract. they will also send some CFX along that will be used to cover the gas costs.

contract calls addPrivilege(…) to “whitelist” accounts
(or use 0x0000000000000000000000000000000000000000 (含义:为所有人代付) )


let’s say Alice deploys the following contract for her dapp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
contract MyCoolDapp {
constructor() {
address addr = 0x0888000000000000000000000000000000000001; // 白名单合约地址
SponsorWhitelistControl swc = SponsorWhitelistControl(addr);

address[] memory a = new address[](1);
a[0] = 0x0000000000000000000000000000000000000000; // 代付所有人
swc.add_privilege(a);
}

function doSomething() public {
// ...
}
}

when Bob calls doSomething() , he has to cover gas and storage

at some point, Alice sends 10 CFX to the SWC contract through this call:

1
2
3
4
swc.setSponsorForGas(
0x8caddbc9f0360b6b96e32fc0a37ffa275ee139f6, // contract
100000000000000000, // upper limit per transaction: 0.1 CFX
);

upper_bound is in Drip but transfer amount is in CFX

she will most likely do this using the JavaScript SDK, or directly from Conflux Studio

this means that at least 100 transactions will be sponsored

when Bob calls doSomething() again, he does not need to pay anymore


blockchain applications and tools

  • 通证 tokens (ERC-20货币通证, NFT非同质通证)
    • stablecoin
    • tokenized art
    • tokenized real-world assets
  • DeFi
    • MoonDex 去中心化交易所
    • MoonSwap
      • AMM(自动做市商)
  • ShuttleFlow 跨链映射协议
    • a building block for DeFi applications
    • move tokens from other chains to Conflux
    • e.g. ETH -> cETH, BTC -> cBTC(资产的跨链转移)
  • Oracles(预言机)
    • allow your smart contract to interact with the world(安全地获取外界的信息)

Resources

Homework of Lecture 6

Lecture 6 - Homework & Resources

Homework is done by a group.

1. Answer the following questions in a few sentences using your own words.

1.a) Why does Ethereum price EVM instructions in GAS instead of using ETH directly?

GAS refers to the computational power required from miners to validate the transaction or smart contract. ETH is the currency used to compensate miners for the GAS required to do the computational work. GAS consumption values are relatively static, while the price of ETH is dynamic and changes overtime.

Charging instructions in GAS thus makes it easier for miners to measure the cost-benefits of a computation and planning their work.

1.b) What is the goal of the gas sponsorship mechanism introduced in Conflux?

Transactions costs on the blockchain are traditionally paid by the user, who benefits from the blockchain network feature.

However, as with the case in any other economy, costs are always pain points and discourages adoption. Adoption is critical for building an ecosystem which value increases from network externalities, which precisely the case with most blockchain networks. In addition, blockchain is not necessarily used to facilitate transactions, so there is the possibility that users of the network do not have any deposited amount with which to pay the transaction fee.

The gas sponsorship mechanism therefore 1) removes a barrier to adoption of the network by new users and 2) increases the application scenarios / flexibility of the smart contract.

1.c) What steps should a developer take so that users of their smart contract do not have to pay for gas?

Implement the Gas Sponsorship Mechanism: allow anyone willing to pay to become a “Sponsor”, donating funds to any contract to pay for the transactions of other whitelisted users (usually new ones with 0 account balance).

Several parameters to include:

  1. Sponsor - records the account providing sponsorship funds for the smart contract
  2. Sponsor balance - records the current balance of the sponsorship funds for the smart contract
  3. Sponsor limit per transaction - sets an upper limit of funds for individual transactions
  4. Whitelist - records, or limits, the accounts that can be sponsored/funded by the smart contract

+1. Gas cost of token transfers [OPTIONAL]

Download lecture-5’s CourseToken project (github.com/Thegaram/cfx-uma-resources/raw/master/cfx-lecture-5.zip 2) or use your own version.

Send some tokens to a new address. How much were you charged for this transfer? Try to explain why.

How does the fee change if you send some more tokens to the same address again?

Create a new “CourseCoin” contract:

Send some tokens to a new address:

  • How much were you charged for this transfer?
    • sent 10, “gasUsed”: “35819“ with gas limit “1000000”, and “gasPrice”: 100
    • Before Vel has CFX: 34363.0111445711547907 CFX
      • SUDDENLY I realize that “Vel” is mining to gain more CFXs. So it won’t work this way.
    • Created another new “CourseCoin” contract with “Calvin”
      • Before Calvin has CFX: 9997.756835937425 CFX
      • After Calvin has CFX: 9997.69433593735 CFX
      • So, total cost is: 0.06250000007457857 CFX

Try to explain why.

We have the calculation form for this as follows:

so what you will pay is

(gas_used x gas_price) + (1/16 CFX x storage_collateralized)

… minus the refund of at most 1/4 x gas_used x gas_price

  • gas_used x gas_price = 35819 * 100 = 3581900 Drips = 3.5819e-12 CFX (In theory)
    • But according to the refund policy:
      • gas_used x gas_price = 3/4 * 1000000 * 100 = 75000000 Drips = 7.5e-11 CFX
  • so we can deduce that:
    • 1/16 CFX x storage_collateralized = 0.06250000007457857 CFX - 7.5e-11 CFX $\approx$ 0.0625 CFX
    • which also implies: storage_collateralized $\approx$ 1

But still, the numbers doesn’t exactly match which is still remaining mystery.

How does the fee change if you send some more tokens to the same address again?

  • sent 1234, gasUsed”: “35883
  • Calvin now has CFX: 9997.694335937275 CFX
  • total cost is: 0.000000000075 CFX
  • It becomes significantly low. I think it’s because the first transaction include data storage initialization which is expensive (1/16 CFX x storage_collateralized).

+1. Sponsored ticket sale [OPTIONAL]

Download lecture-4’s Tickets project (github.com/Thegaram/cfx-uma-resources/raw/master/cfx-lecture-4-tickets.zip) or use your own version.

Change the contract so that people buying tickets through it do not have to pay any transaction fee.

First, trying to find SponsorWhitelistControl.sol.

The import "github.com/Conflux-Chain/conflux-rust/blob/master/internal_contract/contracts/SponsorWhitelistControl.sol"; doesn’t seem working now. Bad news.

But going the website and copying the code is avaliable. And the version is changed. Function Callings are also different.

So I reimplement the SponsorWhitelistControl.sol to fit the demand.

Now we deploy the ticket contract, and there are few changes in the code:

The ticket is priced as 15 CFX for each.

“Leon” has 10000 CFX at first:

Leon buys 1 ticket:

Let’s say Jessica wants to sponsor the contract:

running into a serious trouble…

All the sponsor transactions are timeout and reverted, even the ones I directly send from the 0x0888000000000000000000000000000000000001 panel.

After some parameter adjustments, it worked.

Calvin sponsored 101 CFX to the contract.

Now we can try to buy some more tickets without any charges:

Leon has: 9974.81249999985 CFX

Leon buys 2 tickets: (Each ticket is 5 CFX)

Leon has: 9974.81249999985 CFX - 10 CFX = 9964.81249999985 CFX

Indeed there is no transaction fee for Leon! We made it!

Lecture 7 - DeFi, Reconstruction and Innovation of Finance

Lecture 8 - Blockchain Story

Final Project

https://github.com/stellarkey/uma_bbnc_project