SponsorWhitelistControl
Conflux实现了赞助机制,来补贴智能合约的使用。 这允许余额为零的新账户调用智能合约,前提是执行操作得到赞助(通常由Dapp运营者提供)。 内部的 SponsorWhitelistControl
合约记录了智能合约的赞助信息。
接口
SponsorWhitelistControl 合约的十六进制地址是 0x0888000000000000000000000000000000000001
, 接口是:
pragma solidity >=0.4.15;
contract SponsorWhitelistControl {
/*** Query Functions ***/
/**
* @dev get gas sponsor address of specific contract
* @param contractAddr The address of the sponsored contract
*/
function getSponsorForGas(address contractAddr) public view returns (address) {}
/**
* @dev get current Sponsored Balance for gas
* @param contractAddr The address of the sponsored contract
*/
function getSponsoredBalanceForGas(address contractAddr) public view returns (uint256) {}
/**
* @dev get current Sponsored Gas fee upper bound
* @param contractAddr The address of the sponsored contract
*/
function getSponsoredGasFeeUpperBound(address contractAddr) public view returns (uint256) {}
/**
* @dev get collateral sponsor address
* @param contractAddr The address of the sponsored contract
*/
function getSponsorForCollateral(address contractAddr) public view returns (address) {}
/**
* @dev get current Sponsored Balance for collateral
* @param contractAddr The address of the sponsored contract
*/
function getSponsoredBalanceForCollateral(address contractAddr) public view returns (uint256) {}
/**
* @dev check if a user is in a contract's whitelist
* @param contractAddr The address of the sponsored contract
* @param user The address of contract user
*/
function isWhitelisted(address contractAddr, address user) public view returns (bool) {}
/**
* @dev check if all users are in a contract's whitelist
* @param contractAddr The address of the sponsored contract
*/
function isAllWhitelisted(address contractAddr) public view returns (bool) {}
/*** for contract admin only **/
/**
* @dev contract admin add user to whitelist
* @param contractAddr The address of the sponsored contract
* @param addresses The user address array
*/
function addPrivilegeByAdmin(address contractAddr, address[] memory addresses) public {}
/**
* @dev contract admin remove user from whitelist
* @param contractAddr The address of the sponsored contract
* @param addresses The user address array
*/
function removePrivilegeByAdmin(address contractAddr, address[] memory addresses) public {}
// ------------------------------------------------------------------------
// Someone will sponsor the gas cost for contract `contractAddr` with an
// `upper_bound` for a single transaction.
// ------------------------------------------------------------------------
function setSponsorForGas(address contractAddr, uint upperBound) public payable {}
// ------------------------------------------------------------------------
// Someone will sponsor the storage collateral for contract `contractAddr`.
// ------------------------------------------------------------------------
function setSponsorForCollateral(address contractAddr) public payable {}
// ------------------------------------------------------------------------
// Add commission privilege for address `user` to some contract.
// ------------------------------------------------------------------------
function addPrivilege(address[] memory) public {}
// ------------------------------------------------------------------------
// 从一些合约的地址`user`中移除佣金特权。
// ------------------------------------------------------------------------
function removePrivilege(address[] memory) public {}
/**
* @dev get current available storage points for collateral (activated after CIP-118)
* @param contractAddr The address of the sponsored contract
*/
function getAvailableStoragePoints(address contractAddr) public view returns (uint256) {}
}
如何赞助智能合约
SponsorWhitelistControl
为每个用户建立的合约维护一个白名单,包含有资格获得补贴的账户。 首先,应该使用 addPrivilege(address[] memory)
或 addPrivilegeByAdmin(address contractAddr, address[] memory addresses)
将合格账户添加到白名单中。 值得一提的是,如果将零地址添加到白名单,那么任何账户都将有资格获得补贴。
有两种资源可以被赞助:gas消耗和存储抵押。 这两种资源可以通过 payable
接口 setSponsorForGas(address contractAddr, uint upperBound)
和 setSponsorForCollateral(address contractAddr)
分别进行赞助。
备注
upperBound
(单位:Drip)设置了每笔交易的赞助上限。 交易发送的价值应不低于1000 * upperBound
。
示例
假定您有一个测试合约需要赞助:
pragma solidity >=0.8.0;
import "https://github.com/Conflux-Chain/conflux-rust/blob/master/internal_contract/contracts/SponsorWhitelistControl.sol";
contract CommissionPrivilegeTest {
mapping(uint => uint) public ss;
function add(address account) public {
SponsorWhitelistControl cpc = SponsorWhitelistControl(0x0888000000000000000000000000000000000001);
address[] memory a = new address[](1);
a[0] = account;
cpc.addPrivilege(a);
}
function remove(address account) public {
SponsorWhitelistControl cpc = SponsorWhitelistControl(0x0888000000000000000000000000000000000001);
address[] memory a = new address[](1);
a[0] = account;
cpc.removePrivilege(a);
}
function par_add(uint start, uint end) public {
for (uint i = start; i < end; i++) {
ss[i] = 1;
}
}
}
提供的示例说明了如何部署和赞助测试合约。
"use strict"
const { Conflux, Drip } = require("js-conflux-sdk")
// you need to change the path to the compiled contract
const { abi, bytecode } = require("path/to/CommissionPrivilegeTest.json");
async function main() {
// your secret key to deploy contract
// testnet token can be claimed at https://faucet.confluxnetwork.org/
const PRIVATE_KEY = '0x......';
const cfx = new Conflux({
url: 'https://test.confluxrpc.com',
// logger: console,
networkId: 1,
});
const account = cfx.wallet.addPrivateKey(PRIVATE_KEY); // create account instance
const randomAccount = cfx.wallet.addRandom() // a random account with no cfx
const testContract = cfx.Contract({
abi,
bytecode
})
const contract_addr = (await testContract.constructor().sendTransaction({
from: account.address
}).executed()).contractCreated
console.log(`contract deployed at ${contract_addr}`)
testContract.address = contract_addr
await testContract.add(randomAccount.address).sendTransaction({
from: account.address
}).executed()
console.log(`random address ${randomAccount.address} added to whitelist`)
const sponsor_contract = cfx.InternalContract('SponsorWhitelistControl');
const upperBound = 10n**15n
const upperBoundCfx = Drip(upperBound).toCFX()
const gasSponsorVal = 10n**18n
const storageSponsorVal = 10n ** 18n
if( gasSponsorVal < upperBound * 1000n ) {
throw new Error(`gas sponsor value should be greater than 1000 * upperBound`)
}
await sponsor_contract.setSponsorForGas(contract_addr, upperBound).sendTransaction({
from: account,
value: gasSponsorVal
}).executed();
console.log(`Gas is sponsored with upper bound ${upperBound} Drip (${upperBoundCfx} CFX)`)
await sponsor_contract.setSponsorForCollateral(contract_addr).sendTransaction({
from: account,
value: storageSponsorVal
}).executed();
console.log("Storage collateral is sponsored")
const receipt = await testContract.par_add(1, 3).sendTransaction({
from: randomAccount.address
}).executed()
console.log(`${receipt.transactionHash} is sent`)
console.log(`gas and storage covered by sponsor: ${receipt.gasCoveredBySponsor && receipt.storageCoveredBySponsor}`)
}
main().catch(
console.error
)