当前位置:   article > 正文

solidity基础语法与简单案例20221202_solidity allowance

solidity allowance

1、权限控制合约

核心: 

        嵌套映射 

功能:

        具有多种角色身份时,不同身份具有不同的权限

        角色=>账户=>权限

  1. // SPDX-License-Identifier:MIT
  2. pragma solidity ^0.8.7;
  3. contract AccessControl{
  4. event GrantRole(bytes32 indexed role, address indexed account);
  5. event RevokeRole(bytes32 indexed role, address indexed account);
  6. //使用bytes代替字符串能够降低消耗的gas
  7. mapping(bytes32 => mapping(address => bool)) public roles;
  8. //生成主键
  9. // 0xdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42
  10. bytes32 public constant ADMIN = keccak256(abi.encodePacked("ADMIN"));
  11. //0x2db9fd3d099848027c2383d0a083396f6c41510d7acfd92adc99b6cffcf31e96
  12. bytes32 public constant USER = keccak256(abi.encodePacked("USER"));
  13. constructor(){
  14. _grantrole(ADMIN,msg.sender);
  15. }
  16. modifier onlyRole(bytes32 _role){
  17. require(roles[_role][msg.sender],"not authorized");
  18. _;
  19. }
  20. function _grantrole(bytes32 _role,address _account) internal {
  21. roles[_role][_account] = true;
  22. emit GrantRole(_role,_account);
  23. }
  24. function grantRole(bytes32 _role,address _account) external onlyRole(ADMIN){
  25. _grantrole(_role,_account);
  26. }
  27. function revokeRole(bytes32 _role,address _account) external onlyRole(ADMIN){
  28. roles[_role][_account] = false;
  29. emit RevokeRole(_role,_account);
  30. }
  31. }

2、自毁合约

selfdesctruct(address)

该函数能够强行发送主币 

  1. // SPDX-License-Identifier:MIT
  2. pragma solidity ^0.8.7;
  3. contract Kill{
  4. constructor() payable{}
  5. function kill() external {
  6. selfdestruct(payable(msg.sender));
  7. }
  8. function testCall() external pure returns(uint){
  9. return 123;
  10. }
  11. }
  12. //测试强制发送主币、通过其他合约调用合约自毁功能,并获取主币
  13. contract Helper{
  14. function getBalance() external view returns(uint){
  15. return address(this).balance;
  16. }
  17. function kill(Kill _kill) external {
  18. _kill.kill();
  19. }
  20. }

3、IERC20

ERC20代币标准:不是一套代码,而是一套具有目标功能的接口。

功能包括:

铸造代币、销毁代币

发行代币总额查询、记录并查询某地址代币余额;

向某地址发送一定数量代币;

A地址向B地址批准一定数量的代币、用户调用合约,从A地址向B地址发放一定数量的代币

  1. // SPDX-License-Identifier:MIT
  2. pragma solidity ^0.8.7;
  3. interface IERC20{
  4. //合约发布的代币总量
  5. function totalSupply() external view returns (uint);
  6. //某一个账户的当前余额
  7. function balanceOf(address account) external view returns (uint);
  8. //把当前账户一部分余额发送至另一个账户中
  9. function transfer(address recipient, uint amount) external returns (bool);
  10. //查询某个账户中批准了多少金额
  11. function allowance(address owner, address spender) external view returns (uint);
  12. //为某一个账户批准一定数量的资金
  13. function apporve(address spender,uint amount) external returns (bool);
  14. //从一个账户向另一个账户转移一定量资金
  15. function transferFrom(address spender,address recipient,uint amount) external returns (bool);
  16. event Transfer(address indexed from,address indexed to,uint amount);
  17. event Approval(address indexed owner, address indexed spender, uint amount);
  18. }
  19. //合约ERC20继承IERC20,意味着ERC20用于实现相关接口
  20. contract ERC20 is IERC20 {
  21. uint public override totalSupply;
  22. mapping(address => uint) public override balanceOf;
  23. //allowance:一个地址向另一个地址映射的数字
  24. mapping(address => mapping(address => uint )) public override allowance;
  25. //token name
  26. string public name="Test";
  27. string public symbol = "TEST";
  28. //1*10^8代表了一个整数1
  29. uint public decimals = 18;
  30. //把当前账户一部分余额发送至另一个账户中
  31. function transfer(address recipient, uint amount) external override returns (bool){
  32. balanceOf[msg.sender] -= amount;
  33. balanceOf[recipient] += amount;
  34. emit Transfer(msg.sender,recipient,amount);
  35. return true;
  36. }
  37. //为某一个账户批准一定数量的资金
  38. function apporve(address spender,uint amount) external override returns (bool){
  39. allowance[msg.sender][spender] = amount;
  40. emit Approval(msg.sender,spender,amount);
  41. return true;
  42. }
  43. //合约调用者要求从一个账户向另一个账户转移一定量资金
  44. function transferFrom(address spender,address recipient,uint amount) external override returns (bool){
  45. //合约调用者向代币发送者的账户中批准的余额降低
  46. allowance[spender][msg.sender] -= amount;
  47. //合约调用者的代币账户余额降低
  48. balanceOf[spender] += amount;
  49. //代币接收者的账户余额增加
  50. balanceOf[recipient] += amount;
  51. emit Transfer(spender,recipient,amount);
  52. return true;
  53. }
  54. //铸币
  55. function mint(uint amount) external {
  56. balanceOf[msg.sender] += amount;
  57. totalSupply += amount;
  58. emit Transfer(address(0),msg.sender,amount);
  59. }
  60. //销毁
  61. function burn(uint amount) external{
  62. balanceOf[msg.sender] -= amount;
  63. totalSupply -= amount;
  64. emit Transfer(msg.sender,address(0),amount);
  65. }
  66. }

4、多签钱包

必须有多个人同意的情况下才能把钱包里的钱转出。

  1. // SPDX-License-Identifier:MIT
  2. pragma solidity ^0.8.7;
  3. contract MultiSigWallet{
  4. event Deposit(address indexed sender,uint amount); //存款
  5. event Submit(uint indexed txID); //提交一个交易申请
  6. event Apporve(address indexed owner,uint indexed txId); //合约签名人进行批准
  7. event Revoke(address indexed owner,uint indexed txID); //撤销批准
  8. event Execute(uint indexed txID); //执行批准
  9. address[] public owners; //合约的拥有者
  10. mapping(address => bool) public isOwner; //用于查找某用户是否是签名人
  11. uint public required; //确认数,最少同意进行交易的人数
  12. struct Transaction {
  13. address to;//发送的地址
  14. uint value;//发送的主币数量
  15. bytes data; //如果地址为合约地址,那么还能够执行一些合约中的函数
  16. bool executed; // 标记交易是否执行成功
  17. }
  18. Transaction[] public transactions;//构建一个交易数组,索引值即为ID号
  19. mapping(uint => mapping(address => bool)) public approved; //某一个交易ID下,某一个地址是否批准了该交易
  20. modifier onlyOwner{
  21. require(isOwner[msg.sender],"only owner!");
  22. _;
  23. }
  24. //判断交易id是否存在,由于id即索引,只要交易id小于数组长度,那么判断该交易存在
  25. modifier txExists(uint _txId){
  26. require(0<_txId && _txId< transactions.length,"tx does not exist");
  27. _;
  28. }
  29. //判断签字者是否已经同意
  30. modifier notApproved(uint _txId){
  31. require(!approved[_txId][msg.sender],"tx already approved");
  32. _;
  33. }
  34. //判断是否已经执行交易
  35. modifier notExecuted(uint _txId){
  36. require(!transactions[_txId].executed,"tx already executed");
  37. _;
  38. }
  39. //建立构造函数,用于添加管理者和最小批准人数
  40. constructor(address[] memory _owners,uint _required){
  41. require(_owners.length >0 ,"owner required");//要求管理者数量大于0
  42. require( _required <= _owners.length,//要求最小批准人数大于0且小于等于管理者数量
  43. "invaled required num"
  44. );
  45. //判断地址是否有效:无效地址判断:1、0地址;2、重复地址
  46. for (uint i;i <_owners.length;i++){
  47. address owner = _owners[i];
  48. require(owner != address(0),"invaled owner");
  49. require(!isOwner[owner],"owner is not unique"); //如果地址已经存在过,那么判断为无效地址
  50. isOwner[owner] = true;
  51. owners.push(owner);
  52. }
  53. required=_required;
  54. }
  55. receive() external payable{
  56. emit Deposit(msg.sender,msg.value);
  57. }
  58. //构建交易事件提交函数
  59. function submit(address _to, uint _value, bytes calldata _data) external onlyOwner{
  60. transactions.push(Transaction({
  61. to: _to,
  62. value: _value,
  63. data: _data,
  64. executed: false
  65. }));
  66. emit Submit(transactions.length - 1);//交易it为数组-1
  67. }
  68. //构建交易事件批准函数
  69. function approve(uint _txId)
  70. external
  71. onlyOwner
  72. txExists(_txId)
  73. notApproved(_txId)
  74. notExecuted(_txId)
  75. {
  76. approved[_txId][msg.sender] = true;
  77. emit Apporve(msg.sender,_txId);
  78. }
  79. //计算事件有多少人批准了,获取事件批准数量
  80. function _getApprocalCount(uint _txId) private view returns(uint count){
  81. for(uint i;i<owners.length;i++){
  82. if(approved[_txId][owners[i]]){
  83. count += 1;
  84. }
  85. }
  86. }
  87. function execute(uint _txId) external txExists(_txId) notExecuted(_txId){
  88. require(_getApprocalCount(_txId)>required,"approvals < required");
  89. Transaction storage transaction = transactions[_txId];
  90. transaction.executed = true;
  91. (bool success,) = transaction.to.call{value:transaction.value}(
  92. transaction.data
  93. );
  94. require(success,"tx failed");
  95. emit Execute(_txId);
  96. }
  97. function revoke(uint _txId)
  98. external
  99. onlyOwner
  100. txExists(_txId)
  101. notExecuted(_txId)
  102. {
  103. require(approved[_txId][msg.sender],"tx not approved");
  104. approved[_txId][msg.sender] = false;
  105. emit Revoke(msg.sender,_txId);
  106. }
  107. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/89515
推荐阅读
相关标签
  

闽ICP备14008679号