├── LICENSE ├── STR.sol ├── AddressDiscovery.sol ├── RealDigitalEnableAccount.sol ├── RealTokenizado.sol ├── SwapOneStep.sol ├── .gitignore ├── RealDigitalDefaultAccount.sol ├── README.md ├── CBDCAccessControl.sol ├── SwapTwoSteps.sol ├── KeyDictionary.sol └── RealDigital.sol /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Wireshape 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /STR.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./RealDigital.sol"; 5 | 6 | /** 7 | * @title STR 8 | * @dev Este contrato que simula o STR. Por meio dele, os participantes autorizados podem emitir Real Digital. 9 | * Para o piloto nenhuma validação é feita, bastando que o participante esteja autorizado. 10 | */ 11 | contract STR { 12 | RealDigital private CBDC; // Referência ao contrato do Real Digital para checar se o participante é autorizado. 13 | 14 | /** 15 | * @dev Constrói uma instância do contrato e armazena o endereço do Real Digital. 16 | * @param token address: Endereço do Real Digital. 17 | */ 18 | constructor(RealDigital token) { 19 | CBDC = token; 20 | } 21 | 22 | /** 23 | * @dev Modificador de método: somente participantes podem executar a função. 24 | */ 25 | modifier onlyParticipant() { 26 | require(CBDC.verifyAccount(msg.sender), "Must be participant"); 27 | _; 28 | } 29 | 30 | /** 31 | * @dev Emite a quantidade de Real Digital informada em amount para a própria carteira executora desta função. 32 | * @param amount uint256: Quantidade a ser emitida (obs: lembrar das 2 casas decimais). 33 | */ 34 | function requestToMint(uint256 amount) external onlyParticipant { 35 | CBDC.mint(msg.sender, amount); 36 | } 37 | 38 | /** 39 | * @dev Destrói a quantidade de Real Digital informada em amount da própria carteira executora desta função. 40 | * @param amount uint256: Quantidade a ser destruída (obs: lembrar das 2 casas decimais). 41 | */ 42 | function requestToBurn(uint256 amount) external onlyParticipant { 43 | CBDC.burnFrom(msg.sender, amount); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AddressDiscovery.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/access/AccessControl.sol"; 5 | 6 | /** 7 | * @title AddressDiscovery 8 | * @dev Smart Contract utilitário para facilitar a descoberta dos demais endereços de contratos na rede do Piloto RD. 9 | */ 10 | contract AddressDiscovery is AccessControl { 11 | /** 12 | * @dev Role de acesso, pertencente a autoridade do contrato. 13 | */ 14 | bytes32 public constant ACCESS_ROLE = keccak256("ACCESS_ROLE"); 15 | 16 | /** 17 | * @dev Mapping do endereço dos contratos, a chave é o hash keccak256 do nome do contrato. 18 | */ 19 | mapping(bytes32 => address) public addressDiscovery; 20 | 21 | /** 22 | * @dev Construtor para instanciar o contrato. 23 | * @param _authority address: Autoridade do contrato, pode atualizar os endereços dos contratos. 24 | * @param _admin address: Administrador, pode trocar a autoridade. 25 | */ 26 | constructor(address _authority, address _admin) { 27 | _setRoleAdmin(ACCESS_ROLE, keccak256(abi.encodePacked(_authority))); 28 | _setupRole(DEFAULT_ADMIN_ROLE, _admin); 29 | _setupRole(ACCESS_ROLE, _authority); 30 | } 31 | 32 | /** 33 | * @dev Atualiza o endereço de um contrato, permitido apenas para a autoridade. 34 | * @param smartContract bytes32: Hash keccak256 do nome do contrato. 35 | * @param newAddress address: Novo endereço do contrato. 36 | */ 37 | function updateAddress(bytes32 smartContract, address newAddress) public { 38 | require( 39 | hasRole(ACCESS_ROLE, msg.sender), 40 | "Only the authority can update addresses." 41 | ); 42 | addressDiscovery[smartContract] = newAddress; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /RealDigitalEnableAccount.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./RealDigital.sol"; 5 | 6 | /** 7 | * @title RealDigitalEnableAccount 8 | * @dev Contrato que permite ao participante habilitar outras carteiras de sua propriedade. 9 | */ 10 | contract RealDigitalEnableAccount { 11 | RealDigital private accessControlAddress; // Referência ao contrato do Real Digital para validação de participantes. 12 | bytes32 public constant ACCESS_ROLE = keccak256("ACCESS_ROLE"); 13 | bytes32 public constant DEFAULT_ADMIN_ROLE = 14 | 0x0000000000000000000000000000000000000000000000000000000000000000; 15 | 16 | /** 17 | * @dev Constrói uma instância do contrato e armazena o endereço do contrato do RealDigital, responsável pelas 18 | * verificações de controle de acesso. 19 | * @param _accessControlAddress address: Endereço do contrato de controle de acesso 20 | */ 21 | constructor(address _accessControlAddress) { 22 | accessControlAddress = RealDigital(_accessControlAddress); 23 | } 24 | 25 | /** 26 | * @dev Habilita uma nova carteira para o participante. 27 | * Qualquer carteira previamente habilitada para o participante pode habilitar outras carteiras. 28 | * @param member address: Novo endereço do participante. 29 | */ 30 | function enableAccount(address member) public { 31 | require( 32 | accessControlAddress.verifyAccount(msg.sender), 33 | "Must be participant" 34 | ); 35 | accessControlAddress.enableAccount(member); 36 | } 37 | 38 | /** 39 | * @dev Desabilita a própria carteira que executou a função. 40 | */ 41 | function disableAccount() public { 42 | require( 43 | accessControlAddress.verifyAccount(msg.sender), 44 | "This address is already disabled" 45 | ); 46 | accessControlAddress.disableAccount(msg.sender); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /RealTokenizado.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./RealDigital.sol"; 5 | 6 | /** 7 | * @title RealTokenizado 8 | * @dev Implementação do contrato do Real Tokenizado (DVt e MEt). 9 | * Este contrato herda do Real Digital e todas as funções implementadas. 10 | */ 11 | contract RealTokenizado is RealDigital { 12 | string public participant; // String que representa o nome do participante. 13 | uint256 public cnpj8; // Uitn256 que representa o número da instituição. 14 | address public reserve; // Carteira de reserva da instituição participante. 15 | 16 | /** 17 | * @dev Construtor do token do Real Tokenizado. 18 | * Invoca o construtor do ERC20 e dá permissão de autoridade para a carteira do BCB. 19 | * @param _name string: Nome do token: Real Tokenizado (Instituiçâo). 20 | * @param _symbol string: Símbolo do token: BRL. 21 | * @param _authority address: Carteira responsável por emitir, resgatar, mover e congelar fundos (BCB). 22 | * @param _admin address: Carteira responsável por administrar o controle de acessos (BCB). 23 | * @param _participant string: Identificação do participante como string. 24 | * @param _cnpj8 uint256: Primeiros 8 digitos do CNPJ da instituição. 25 | * @param _reserve address: Carteira de reserva da instituição. 26 | */ 27 | constructor( 28 | string memory _name, 29 | string memory _symbol, 30 | address _authority, 31 | address _admin, 32 | string memory _participant, 33 | uint256 _cnpj8, 34 | address _reserve 35 | ) RealDigital(_name, _symbol, _authority, _admin) { 36 | participant = _participant; 37 | cnpj8 = _cnpj8; 38 | reserve = _reserve; 39 | } 40 | 41 | /** 42 | * @dev Função para atualizar a carteira de reserva do token. 43 | * A carteira de reserva é usada pelo DvP. 44 | * @param newReserve Carteira da autoridade (Instituição). 45 | */ 46 | function updateReserve( 47 | address newReserve 48 | ) public onlyRole(DEFAULT_ADMIN_ROLE) { 49 | reserve = newReserve; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SwapOneStep.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./RealDigital.sol"; 5 | import "./RealTokenizado.sol"; 6 | 7 | /** 8 | * @title SwapOneStep 9 | * @dev Este contrato implementa a troca de Real Tokenizado entre dois participantes distintos. 10 | * 11 | * A troca destrói Real Tokenizado do cliente pagador, transfere Real Digital do participante pagador para o 12 | * participante recebedor e emite Real Tokenizado para o cliente recebedor. 13 | * 14 | * Todos os passos dessa operação de swap são realizados em apenas uma transação. 15 | */ 16 | contract SwapOneStep { 17 | RealDigital private CBDC; // Referência ao contrato para que seja efetuada a movimentação de Real Digital. 18 | 19 | /** 20 | * @dev Evento de swap executado. 21 | * @param senderNumber uint256: O CNPJ8 do pagador. 22 | * @param receiverNumber uint256: O CNPJ8 do recebedor. 23 | * @param sender address: A carteira do pagador. 24 | * @param receiver address: A carteira do recebedor. 25 | * @param amount uint256: O valor que foi movimentado. 26 | */ 27 | event SwapExecuted( 28 | uint256 senderNumber, 29 | uint256 receiverNumber, 30 | address sender, 31 | address receiver, 32 | uint256 amount 33 | ); 34 | 35 | /** 36 | * @dev Constrói uma instância do contrato e armazena o endereço do contrato do Real Digital. 37 | * @param _CBDC address: Endereço do contrato do Real Digital. 38 | */ 39 | constructor(RealDigital _CBDC) { 40 | CBDC = _CBDC; 41 | } 42 | 43 | /** 44 | * @dev Transfere o Real Tokenizado do cliente pagador para o recebedor. 45 | * O cliente pagador é identificado pela carteira que estiver executando esta função. 46 | * @param tokenSender address: O endereço do contrato de Real Tokenizado do participante pagador. 47 | * @param tokenReceiver address: O endereço do contrato de Real Tokenizado do participante recebedor. 48 | * @param receiver address: O endereço do cliente recebedor. 49 | * @param amount uint256: O valor a ser movimentado. 50 | */ 51 | function executeSwap( 52 | RealTokenizado tokenSender, 53 | RealTokenizado tokenReceiver, 54 | address receiver, 55 | uint256 amount 56 | ) public { 57 | tokenSender.burnFrom(msg.sender, amount); 58 | CBDC.move(tokenSender.reserve(), tokenReceiver.reserve(), amount); 59 | tokenReceiver.mint(receiver, amount); 60 | 61 | emit SwapExecuted( 62 | tokenSender.cnpj8(), 63 | tokenReceiver.cnpj8(), 64 | msg.sender, 65 | receiver, 66 | amount 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | # Artifacts 133 | artifacts 134 | 135 | # Deps 136 | .deps -------------------------------------------------------------------------------- /RealDigitalDefaultAccount.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/access/AccessControl.sol"; 5 | import "./RealDigital.sol"; 6 | 7 | /** 8 | * @title RealDigitalDefaultAccount 9 | * @dev Contrato que permite aos participantes trocarem sua carteira default. 10 | */ 11 | contract RealDigitalDefaultAccount is AccessControl { 12 | RealDigital private CBDC; // Referência ao contrato do Real Digital para validação de participantes. 13 | address private authority; // Autoridade do contrato. Adiciona carteiras default. 14 | address private admin; // Administrador do contrato. Permite trocar a autoridade. 15 | 16 | /** 17 | * @dev Mapping das contas default. 18 | * Chave é o CNPJ8 do participante. 19 | */ 20 | mapping(uint256 => address) private _defaultAccount; 21 | 22 | /** 23 | * @dev Modificador de método: somente participantes podem alterar suas carteiras default. 24 | */ 25 | modifier onlyParticipant() { 26 | require(CBDC.verifyAccount(msg.sender), "Must be participant"); 27 | _; 28 | } 29 | 30 | /** 31 | * @dev Construtor para instanciar o contrato. 32 | * @param token address: Endereço do Real Digital. 33 | * @param _authority address: Autoridade do contrato. Adiciona carteiras default. 34 | * @param _admin address: Administrador do contrato. Permite trocar a autoridade. 35 | */ 36 | constructor(RealDigital token, address _authority, address _admin) { 37 | CBDC = token; 38 | authority = _authority; 39 | admin = _admin; 40 | } 41 | 42 | /** 43 | * @dev Adiciona a primeira carteira default para um participante. 44 | * É permitido apenas para a autoridade. 45 | * @param cnpj8 uint256: CNPJ8 do participante. 46 | * @param wallet address: Carteira. 47 | */ 48 | function addDefaultAccount(uint256 cnpj8, address wallet) public { 49 | require(msg.sender == authority, "Must be authority"); 50 | _defaultAccount[cnpj8] = wallet; 51 | } 52 | 53 | /** 54 | * @dev Permite ao participante trocar sua carteira default. 55 | * @param cnpj8 uint256: CNPJ8 do participante. 56 | * @param newWallet address: Carteira. 57 | */ 58 | function updateDefaultWallet( 59 | uint256 cnpj8, 60 | address newWallet 61 | ) public onlyParticipant { 62 | require( 63 | _defaultAccount[cnpj8] == msg.sender, 64 | "Must be current default account" 65 | ); 66 | _defaultAccount[cnpj8] = newWallet; 67 | } 68 | 69 | /** 70 | * @dev Retorna a carteira default de um participante. 71 | * @param cnpj8 uint256: CNPJ8 do participante. 72 | * @return address Retorna o endereço da carteira default do participante. 73 | */ 74 | function defaultAccount(uint256 cnpj8) public view returns (address) { 75 | return _defaultAccount[cnpj8]; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Real Digital Smart Contracts 2 | Este repositório contém os smart contracts desenvolvidos pela Wire Labs para fins educacionais e de pesquisa com base na documentação do Piloto do Real Digital fornecida pelo Bacen (Banco Central do Brasil) em 03-07-2023. 3 | 4 | O Real Digital, ou Drex - nome definido para a nova moeda digital do Brasil, é um token ERC20 conceitual para uma Moeda Digital de Banco Central (da sigla em inglês CBDC, Central Bank Digital Currency). 5 | 6 | ## Programa Real Digital Simulado 7 | A Wireshape fornece um ambiente de testes simulado para o Real Digital CBDC. Neste ambiente você pode experimentar e interagir com os contratos inteligentes do Real Digital Simulado **sem precisar configurar sua própria infraestrutura**. 8 | 9 | Para participar do programa, preencha o formulário com as informações necessárias para o cadastro na rede como **Instituição Financeira Simulada**: 10 | 11 | 📌 PT: [https://wireshape.org/use-cases/drex-sandbox-pt](https://wireshape.org/use-cases/drex-sandbox-pt) 12 | 13 | 📌 EN: [https://wireshape.org/use-cases/drex-sandbox](https://wireshape.org/use-cases/drex-sandbox) 14 | 15 | ### Recursos do Programa: 16 | 17 | 🔹 **Smart Contracts:** Explore e teste os smart contracts desenvolvidos pela Wire Labs com base nas ABIs fornecidas pelo Banco Central. 18 | 19 | 🔹 **Acesso RPC Simulado:** Interaja com os smart contracts através de um servidor RPC dedicado fornecido pela Wireshape, sem a necessidade de configurar sua própria infraestrutura. Todos os contratos serão implementados e publicados na rede pela Wireshape. 20 | 21 | 🔹 **Block Explorer:** Verifique todas as transações e faça consultas nos smart contracts da rede do Real Digital Simulado. 22 | 23 | ⚠️ **Lembre-se:** O programa de ambiente de testes simulado da Wireshape não possui afiliação oficial com o Banco Central. Interaja com os smart contracts em um ambiente simulado por sua própria conta e risco. 24 | 25 | ## Aviso 26 | 27 | Os contratos inteligentes aqui fornecidos não possuem qualquer vínculo, endosso ou relação direta com o Banco Central do Brasil. Por se tratar de uma reconstrução com finalidade de estudo, podem não abranger integralmente a implementação ou o comportamento pretendido do Real Digital e não devem ser usados em um ambiente de produção. 28 | 29 | ## Licença 30 | 31 | Este projeto está licenciado sob a Licença MIT. Para mais informações, consulte o arquivo [LICENSE](https://github.com/wireshape/real-digital-smart-contracts/blob/main/LICENSE). 32 | 33 | ## Créditos e Agradecimentos 34 | 35 | Os smart contracts aqui disponibilizados foram desenvolvidos pela Wire Labs e seus contribuidores. Gostaríamos de agradecer à equipe do Bacen pela liberação das [ABIs do Real Digital](https://github.com/bacen/pilotord-kit-onboarding) e aos esforços de reconstrução dos contratos que nos ajudaram em estudos e testes, como https://github.com/begrossi/pilotord-kit-onboarding/tree/main. 36 | 37 | ## Contato 38 | 39 | Para qualquer dúvida, sinta-se à vontade para entrar em contato. 40 | -------------------------------------------------------------------------------- /CBDCAccessControl.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/access/AccessControl.sol"; 5 | 6 | /** 7 | * @title CBDCAccessControl 8 | * @dev Smart Contract responsável pela camada de controle de acesso para o Real Digital/Tokenizado. 9 | * Suas principais funcionalidades são: 10 | * - Determinar quais carteiras podem enviar/receber tokens. 11 | * - Controlar os papeis de qual endereço pode emitir/resgatar/congelar saldo de uma carteira. 12 | */ 13 | abstract contract CBDCAccessControl is AccessControl { 14 | bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); // Role que permite pausar o contrato. 15 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); // Role que permite fazer o mint nos contratos de token. 16 | bytes32 public constant ACCESS_ROLE = keccak256("ACCESS_ROLE"); // Role que permite habilitar um endereço. 17 | bytes32 public constant MOVER_ROLE = keccak256("MOVER_ROLE"); // Role que permite acesso à função move, ou seja, transferir o token de outra carteira. 18 | bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); // Role que permite acesso à função burn. 19 | bytes32 public constant FREEZER_ROLE = keccak256("FREEZER_ROLE"); // Role que permite bloquear saldo de uma carteira, por exemplo para o swap de dois passos. 20 | 21 | /** 22 | * @dev Mapping das contas autorizadas a receber o token. 23 | */ 24 | mapping(address => bool) private _authorizedAccounts; 25 | 26 | /** 27 | * @dev Evento de carteira habilitada. 28 | * @param member address: Carteira habilitada. 29 | */ 30 | event EnabledAccount(address indexed member); 31 | 32 | /** 33 | * @dev Evento de carteira desabilitada. 34 | * @param member address: Carteira desabilitada. 35 | */ 36 | event DisabledAccount(address indexed member); 37 | 38 | /** 39 | * @dev Constrói uma instância da contrato, armazenando os argumentos informados. 40 | * @param _authority address: Autoridade do contrato, pode fazer todas as operações com o token. 41 | * @param _admin address: Administrador do contrato, pode trocar a autoridade do contrato caso seja necessário. 42 | */ 43 | constructor(address _authority, address _admin) { 44 | _setupRole(DEFAULT_ADMIN_ROLE, _admin); 45 | _setupRole(ACCESS_ROLE, _authority); 46 | _setupRole(MINTER_ROLE, _authority); 47 | _setupRole(BURNER_ROLE, _authority); 48 | _setupRole(MOVER_ROLE, _authority); 49 | _setupRole(FREEZER_ROLE, _authority); 50 | _setupRole(PAUSER_ROLE, _admin); 51 | 52 | bytes32 _adminHash = keccak256(abi.encodePacked(_admin)); 53 | 54 | _setRoleAdmin(DEFAULT_ADMIN_ROLE, _adminHash); 55 | } 56 | 57 | /** 58 | * @dev Modificador que checa se tanto o pagador quanto o recebedor estão habilitados a receber o token. 59 | * @param from address: Carteira do pagador. 60 | * @param to address: Carteira do recebedor. 61 | */ 62 | modifier checkAccess(address from, address to) { 63 | if (from != address(0)) { 64 | require(verifyAccount(from), "Sender is not enabled"); 65 | } else if (to != address(0)) { 66 | require(verifyAccount(to), "Recipient is not enabled"); 67 | } 68 | _; 69 | } 70 | 71 | /** 72 | * @dev Habilita a carteira a receber o token. 73 | * @param member address: Carteira a ser habilitada. 74 | */ 75 | function enableAccount(address member) public { 76 | require( 77 | hasRole(ACCESS_ROLE, msg.sender), 78 | "Only the authority can enable account" 79 | ); 80 | 81 | _authorizedAccounts[member] = true; 82 | emit EnabledAccount(member); 83 | } 84 | 85 | /** 86 | * @dev Desabilita a carteira. 87 | * @param member address: Carteira a ser desabilitada. 88 | */ 89 | function disableAccount(address member) public { 90 | require( 91 | hasRole(ACCESS_ROLE, msg.sender), 92 | "Only the authority can disable account" 93 | ); 94 | 95 | _authorizedAccounts[member] = false; 96 | emit DisabledAccount(member); 97 | } 98 | 99 | /** 100 | * @dev Checa se a carteira pode receber o token. 101 | * @param account address: Carteira a ser checada. 102 | * @return value bool: Retorna um valor booleano indicando a condição da carteira. 103 | */ 104 | function verifyAccount(address account) public view returns (bool) { 105 | return _authorizedAccounts[account]; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /SwapTwoSteps.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./RealDigital.sol"; 5 | import "./RealTokenizado.sol"; 6 | 7 | /** 8 | * @title SwapTwoSteps 9 | * @dev Este contrato implementa a troca de Real Tokenizado entre dois participantes distintos. 10 | * A troca destrói Real Tokenizado do cliente pagador, transfere Real Digital do participante pagador para o 11 | * participante recebedor e emite Real Tokenizado para o cliente recebedor. 12 | * A operação de swap implementada neste contrato é realizada em duas transações: uma de proposta e outra de aceite. 13 | */ 14 | contract SwapTwoSteps { 15 | RealDigital private CBDC; // Referência ao contrato para que seja efetuada a movimentação de Real Digital. 16 | 17 | /** 18 | * @dev Enumeração com as possíveis situações de uma operação de swap. 19 | */ 20 | enum SwapStatus { 21 | PENDING, // Operação de _swap_ registrada, pendente de cancelamento ou execução. 22 | EXECUTED, // Operação de _swap_ executada. 23 | CANCELLED // Operação de _swap_ cancelada. 24 | } 25 | 26 | struct SwapProposal { 27 | RealTokenizado tokenSender; // O endereço do contrato de Real Tokenizado do participante pagador. 28 | RealTokenizado tokenReceiver; // O endereço do contrato de Real Tokenizado do participante recebedor. 29 | address sender; // O endereço da wallet do cliente pagador. 30 | address receiver; // O endereço da wallet do cliente recebedor. 31 | uint256 amount; // Quantidade de Reais a ser movimentada. 32 | SwapStatus status; // Situação atual da operação. 33 | uint256 timestamp; 34 | } 35 | 36 | uint256 private proposalCounter; // Número da última proposta. 37 | 38 | /** 39 | * @dev Mapping de propostas de swap. 40 | */ 41 | mapping(uint256 => SwapProposal) public swapProposals; 42 | 43 | /** 44 | * @dev Evento de início do swap. 45 | * @param proposalId uint256: Id da proposta. 46 | * @param senderNumber uint256: CNPJ8 do pagador 47 | * @param receiverNumber uint256: CNPJ8 do recebedor 48 | * @param sender address: Endereço do pagador 49 | * @param receiver address: Endereço do recebedor 50 | * @param amount uint256: Valor 51 | */ 52 | event SwapStarted( 53 | uint256 proposalId, 54 | uint256 senderNumber, 55 | uint256 receiverNumber, 56 | address sender, 57 | address receiver, 58 | uint256 amount 59 | ); 60 | 61 | /** 62 | * @dev Evento de swap executado. 63 | * @param proposalId uint256: Id da proposta. 64 | * @param senderNumber uint256: CNPJ8 do pagador. 65 | * @param receiverNumber uint256: CNPJ8 do recebedor. 66 | * @param sender address: Endereço do pagador. 67 | * @param receiver address: Endereço do recebedor. 68 | * @param amount uint256: Valor 69 | */ 70 | event SwapExecuted( 71 | uint256 proposalId, 72 | uint256 senderNumber, 73 | uint256 receiverNumber, 74 | address sender, 75 | address receiver, 76 | uint256 amount 77 | ); 78 | 79 | /** 80 | * @dev Evento de swap cancelado. 81 | * @param proposalId uint256: Id da proposta. 82 | * @param reason string: Razão do cancelamento. 83 | */ 84 | event SwapCancelled(uint256 proposalId, string reason); 85 | 86 | /** 87 | * @dev Evento de proposta expirada. A proposta expira em 1 minuto. 88 | * @param proposalId uint256: Id da proposta. 89 | */ 90 | event ExpiredProposal(uint256 proposalId); 91 | 92 | /** 93 | * @dev Construtor para instanciar o contrato. 94 | * @param _CBDC address: Endereço do contrato do Real Digital. 95 | */ 96 | constructor(RealDigital _CBDC) { 97 | CBDC = _CBDC; 98 | proposalCounter = 0; 99 | } 100 | 101 | /** 102 | * @dev Cria a proposta de swap. 103 | * @param tokenSender address: Endereço do contrato de Real Tokenizado do pagador. 104 | * @param tokenReceiver address: Endereço do contrato de Real Tokenizado do recebedor. 105 | * @param receiver address: Endereço do cliente recebedor. 106 | * @param amount uint256: Valor. 107 | */ 108 | function startSwap( 109 | RealTokenizado tokenSender, 110 | RealTokenizado tokenReceiver, 111 | address receiver, 112 | uint256 amount 113 | ) public { 114 | proposalCounter += 1; 115 | swapProposals[proposalCounter] = SwapProposal({ 116 | tokenSender: tokenSender, 117 | tokenReceiver: tokenReceiver, 118 | sender: msg.sender, 119 | receiver: receiver, 120 | amount: amount, 121 | status: SwapStatus.PENDING, 122 | timestamp: block.timestamp 123 | }); 124 | 125 | emit SwapStarted( 126 | proposalCounter, 127 | tokenSender.cnpj8(), 128 | tokenReceiver.cnpj8(), 129 | msg.sender, 130 | receiver, 131 | amount 132 | ); 133 | } 134 | 135 | /** 136 | * @dev Aceita a proposta de swap, executável apenas pelo recebedor. 137 | * @param proposalId uint256: Id da proposta. 138 | */ 139 | function executeSwap(uint256 proposalId) public { 140 | SwapProposal storage proposal = swapProposals[proposalId]; 141 | require( 142 | proposal.receiver == msg.sender, 143 | "Only the receiver can execute the swap." 144 | ); 145 | require( 146 | proposal.status == SwapStatus.PENDING, 147 | "Cannot execute swap, status is not PENDING." 148 | ); 149 | require( 150 | proposal.timestamp + 7 days > block.timestamp, 151 | "Proposal expired" 152 | ); 153 | 154 | proposal.tokenSender.burnFrom(proposal.sender, proposal.amount); 155 | CBDC.move( 156 | proposal.tokenSender.reserve(), 157 | proposal.tokenReceiver.reserve(), 158 | proposal.amount 159 | ); 160 | proposal.tokenReceiver.mint(proposal.receiver, proposal.amount); 161 | 162 | proposal.status = SwapStatus.EXECUTED; 163 | 164 | emit SwapExecuted( 165 | proposalId, 166 | proposal.tokenSender.cnpj8(), 167 | proposal.tokenReceiver.cnpj8(), 168 | proposal.sender, 169 | proposal.receiver, 170 | proposal.amount 171 | ); 172 | } 173 | 174 | /** 175 | * @dev Cancela a proposta. 176 | * Pode ser executada tanto pelo pagador quanto pelo recebedor. 177 | * @param proposalId uint256: Id da proposta 178 | * @param reason string: Razão do cancelamento 179 | */ 180 | function cancelSwap(uint256 proposalId, string memory reason) public { 181 | SwapProposal storage proposal = swapProposals[proposalId]; 182 | require( 183 | msg.sender == proposal.sender || msg.sender == proposal.receiver, 184 | "Only the sender or receiver can cancel the swap." 185 | ); 186 | require( 187 | proposal.status == SwapStatus.PENDING, 188 | "Cannot cancel swap, status is not PENDING." 189 | ); 190 | 191 | proposal.status = SwapStatus.CANCELLED; 192 | emit SwapCancelled(proposalId, reason); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /KeyDictionary.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "./RealDigital.sol"; 6 | 7 | /** 8 | * @title KeyDictionary 9 | * @dev Contrato que representa a consulta de carteiras de clientes. É um contrato de simulação de um diretório de informações. 10 | * Este contrato será usado somente durante o piloto. 11 | */ 12 | contract KeyDictionary { 13 | /** 14 | * @dev Dados do cliente 15 | */ 16 | struct CustomerData { 17 | uint256 taxId; // O CPF do cliente 18 | uint256 bankNumber; // O código da participante 19 | uint256 account; // A conta do cliente 20 | uint256 branch; // A agência do cliente 21 | address wallet; // A carteira do cliente 22 | bool registered; // Registrado ou não 23 | address owner; // A carteira do participante que inseriu o cliente 24 | } 25 | 26 | /** 27 | * @dev [Sugestão de implementação] Armazena uma requisição de troca de dono de chave. 28 | */ 29 | struct KeyRequest { 30 | bytes32 key; // A chave do cliente. 31 | uint256 timestamp; // [Sugestão de implementação] verificacão de tempo de expiração da requisição. 32 | CustomerData data; // Os novos dados do cliente associado à chave. 33 | } 34 | 35 | RealDigital private CBDC; // Referência para o contrato de Real Digital. 36 | 37 | mapping(bytes32 => CustomerData) private customers; // Mapping de dados dos clientes. 38 | mapping(address => bytes32) private wallets; // Mapping das carteiras. 39 | mapping(uint256 => KeyRequest) private keyRequests; // Mapping das requisições de troca de dono de chave. 40 | 41 | /** 42 | * @dev Evento de solicitação de troca de dono de chave. 43 | * @param owner address: O atual dono da chave. 44 | * @param proposalId uint256: Id da proposta. 45 | * @param key bytes32: A chave. 46 | */ 47 | event KeyRequested(address owner, uint256 proposalId, bytes32 key); 48 | 49 | /** 50 | * @dev Modificador de método: somente participantes podem executar o método. 51 | */ 52 | modifier onlyParticipant() { 53 | require(CBDC.verifyAccount(msg.sender), "Must be participant"); 54 | _; 55 | } 56 | 57 | /** 58 | * @dev Constrói uma instância do contrato e armazena o endereço do contrato do Real Digital. 59 | * @param token address: Endereço do contrato do Real Digital. 60 | */ 61 | constructor(RealDigital token) { 62 | CBDC = token; 63 | } 64 | 65 | /** 66 | * @dev Adiciona os dados do cliente, vinculando à chave key. 67 | * @param key bytes32: A chave. 68 | * @param _taxId uint256: O CPF do cliente. 69 | * @param _bankNumber uint256: O ID do participante. 70 | * @param _account uint256: A conta do cliente. 71 | * @param _branch uint256: A agência do cliente. 72 | * @param _wallet address: A carteira do cliente. 73 | */ 74 | function addAccount( 75 | bytes32 key, 76 | uint256 _taxId, 77 | uint256 _bankNumber, 78 | uint256 _account, 79 | uint256 _branch, 80 | address _wallet 81 | ) public onlyParticipant { 82 | customers[key] = CustomerData( 83 | _taxId, 84 | _bankNumber, 85 | _account, 86 | _branch, 87 | _wallet, 88 | false, 89 | msg.sender 90 | ); 91 | wallets[_wallet] = key; 92 | } 93 | 94 | /** 95 | * @dev Retorna a carteira do cliente com base na sua chave key. 96 | * @param key bytes32: A chave cuja carteira está sendo buscada. 97 | */ 98 | function getWallet(bytes32 key) public view returns (address) { 99 | return customers[key].wallet; 100 | } 101 | 102 | /** 103 | * @dev Retorna a chave do cliente com base na sua carteira. 104 | * @param wallet address: A carteira do cliente. 105 | */ 106 | function getKey(address wallet) public view returns (bytes32) { 107 | return wallets[wallet]; 108 | } 109 | 110 | /** 111 | * @dev Retorna todos os dados do cliente. 112 | * @param key bytes32: A chave do cliente solicitado. 113 | */ 114 | function getCustomerData( 115 | bytes32 key 116 | ) public view returns (CustomerData memory) { 117 | return customers[key]; 118 | } 119 | 120 | /** 121 | * @dev Atualiza os dados do cliente vinculado à chave key. 122 | * Apenas o dono da carteira do participante ao qual o cliente vinculou sua chave pode alterar os dados por esta função. 123 | * @param key bytes32: A nova chave do cliente. 124 | * @param _taxId uint256: O novo CPF do cliente. 125 | * @param _bankNumber uint256: O novo ID do participante responsável pelo cliente. 126 | * @param _account uint256: A nova conta do cliente. 127 | * @param _branch uint256: A nova agência do cliente. 128 | * @param _wallet address: A nova carteira do cliente. 129 | */ 130 | function updateData( 131 | bytes32 key, 132 | uint256 _taxId, 133 | uint256 _bankNumber, 134 | uint256 _account, 135 | uint256 _branch, 136 | address _wallet 137 | ) public onlyParticipant { 138 | require( 139 | customers[key].owner == msg.sender, 140 | "Only owner can update data" 141 | ); 142 | customers[key] = CustomerData( 143 | _taxId, 144 | _bankNumber, 145 | _account, 146 | _branch, 147 | _wallet, 148 | false, 149 | msg.sender 150 | ); 151 | wallets[_wallet] = key; 152 | } 153 | 154 | /** 155 | * @dev Requisita uma chave que pertence a outro participante. 156 | * @param key bytes32: A chave requisitada. 157 | * @param _taxId uint256: O CPF do cliente requisitante. 158 | * @param _bankNumber uint256: ID do participante responsável pelo cliente requisitante. 159 | * @param _account uint256: A conta do cliente requisitante. 160 | * @param _branch uint256: A agência do cliente requisitante. 161 | * @param _wallet address: A carteira do cliente requisitante. 162 | */ 163 | function requestKey( 164 | bytes32 key, 165 | uint256 _taxId, 166 | uint256 _bankNumber, 167 | uint256 _account, 168 | uint256 _branch, 169 | address _wallet 170 | ) public onlyParticipant { 171 | require(!customers[key].registered, "Key already registered"); 172 | require(customers[key].owner != msg.sender, "Cannot request own key"); 173 | 174 | /** 175 | * @dev Cria uma proposta de troca de dono de chave. 176 | */ 177 | uint256 proposalId = uint256( 178 | keccak256(abi.encodePacked(msg.sender, block.timestamp)) 179 | ); 180 | 181 | /** 182 | * @dev Armazena a proposta 183 | */ 184 | keyRequests[proposalId] = KeyRequest( 185 | key, 186 | block.timestamp, 187 | CustomerData( 188 | _taxId, 189 | _bankNumber, 190 | _account, 191 | _branch, 192 | _wallet, 193 | false, 194 | msg.sender 195 | ) 196 | ); 197 | 198 | /** 199 | * @dev Emite o evento de solicitação de troca de dono de chave 200 | */ 201 | emit KeyRequested(msg.sender, proposalId, key); 202 | } 203 | 204 | /** 205 | * @dev Autoriza a alteração de dados proposta pelo id proposalId para a chave key. 206 | * @param proposalId uint256: Id da proposta. 207 | * @param key bytes32: A chave cujos dados serão alterados. 208 | */ 209 | function authorizeKey( 210 | uint256 proposalId, 211 | bytes32 key 212 | ) public onlyParticipant { 213 | require( 214 | keyRequests[proposalId].key == key, 215 | "ProposalId does not match key" 216 | ); 217 | require( 218 | customers[key].owner == msg.sender, 219 | "Only owner can authorize key transfer" 220 | ); 221 | 222 | /** 223 | * @dev [Sugestão de implementação] verificacão de tempo de expiração da proposta 224 | */ 225 | require( 226 | keyRequests[proposalId].timestamp + 7 days > block.timestamp, 227 | "Proposal expired" 228 | ); 229 | 230 | /** 231 | * @dev Atualiza os dados do cliente 232 | */ 233 | customers[key] = keyRequests[proposalId].data; 234 | 235 | /** 236 | * @dev Atualiza o mapping de carteiras 237 | */ 238 | wallets[keyRequests[proposalId].data.wallet] = key; 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /RealDigital.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | import "@openzeppelin/contracts/security/Pausable.sol"; 6 | import "@openzeppelin/contracts/utils/math/SafeMath.sol"; 7 | 8 | import "./CBDCAccessControl.sol"; 9 | 10 | /** 11 | * @title RealDigital 12 | */ 13 | contract RealDigital is ERC20, CBDCAccessControl, Pausable { 14 | // Uso do SafeMath para prevenir overflow e underflow 15 | using SafeMath for uint256; 16 | 17 | /** 18 | * @dev Mapping das carteiras e respectivo valor congelado. 19 | */ 20 | mapping(address => uint256) private frozenBalances; 21 | 22 | /** 23 | * @dev Evento emitido quando um valor de uma carteira é congelado. 24 | * @param wallet address: Carteira que teve o fundo congelado. 25 | * @param amount uint256: Quantidade congelada. 26 | */ 27 | event FrozenBalance(address wallet, uint256 amount); 28 | 29 | /** 30 | * @dev Modifier para verificar se um endereço possui fundos suficientes. 31 | * Usado no _beforeTokenTransfer. 32 | * @param from address: Carteira origem 33 | * @param amount uint256: Quantidade de tokens. 34 | */ 35 | modifier checkFrozenBalance(address from, uint256 amount) { 36 | if (from != address(0)) { 37 | require( 38 | balanceOf(from) - frozenBalanceOf(from) >= amount, 39 | "RealDigital: insufficient balance" 40 | ); 41 | } 42 | _; 43 | } 44 | 45 | /** 46 | * @dev Construtor do token do Real Digital. 47 | * Invoca o construtor do ERC20 e dá permissão de autoridade para a carteira do BCB. 48 | * @param _name string: Nome do token: Real Digital. 49 | * @param _symbol string: Símbolo do token: BRL 50 | * @param _authority address: Carteira responsável por emitir, resgatar, mover e congelar fundos (BCB). 51 | * @param _admin address: Carteira responsável por administrar o controle de acessos (BCB). 52 | */ 53 | constructor( 54 | string memory _name, 55 | string memory _symbol, 56 | address _authority, 57 | address _admin 58 | ) ERC20(_name, _symbol) CBDCAccessControl(_authority, _admin) {} 59 | 60 | /** 61 | * @dev Função para pausar o token em casos necessários, bloqueando-o para todas as operações. 62 | */ 63 | function pause() public whenNotPaused onlyRole(PAUSER_ROLE) { 64 | _pause(); 65 | } 66 | 67 | /** 68 | * @dev Função para despausar o token em casos necessários, desbloqueando-o para todas as operações. 69 | */ 70 | function unpause() public whenPaused onlyRole(PAUSER_ROLE) { 71 | _unpause(); 72 | } 73 | 74 | /** 75 | * @dev Gatilho executado sempre que é solicitada uma movimentação de token, inclusive na criação e destruição de tokens. 76 | * Condições de chamada: 77 | * - quando from é zero, amount tokens serão emitidos to. 78 | * - quando to é zero, amount do from tokens serão destruídos. 79 | * - from e to nunca serão simultaneamente zero. 80 | * - from e to devem estar registrados como participantes. 81 | */ 82 | function _beforeTokenTransfer( 83 | address from, 84 | address to, 85 | uint256 amount 86 | ) 87 | internal 88 | virtual 89 | override 90 | whenNotPaused 91 | checkFrozenBalance(from, amount) 92 | checkAccess(from, to) 93 | { 94 | super._beforeTokenTransfer(from, to, amount); 95 | } 96 | 97 | /** 98 | * @dev Destrói um determinado valor da carteira. 99 | * Veja {ERC20-burn}. 100 | */ 101 | function burn(uint256 amount) public onlyRole(BURNER_ROLE) whenNotPaused { 102 | _burn(_msgSender(), amount); 103 | } 104 | 105 | /** 106 | * @dev Destrói amount tokens da account, deduzindo alllowance do executor. Olhe {ERC20-_burn} e {ERC20-allowance}. 107 | * Requerimentos: 108 | * - o executor deve possuir autorização de mover fundos da accounts de no mínimo o amount. 109 | */ 110 | function burnFrom( 111 | address account, 112 | uint256 amount 113 | ) public virtual whenNotPaused { 114 | uint256 decreasedAllowance = allowance(account, _msgSender()) - amount; 115 | _approve(account, _msgSender(), decreasedAllowance); 116 | _burn(account, amount); 117 | } 118 | 119 | /** 120 | * @dev Retorna o número de casas decimais utilizadas na representação do valor do token. 121 | * Por exemplo, se decimals for igual a 2, um saldo de 505 tokens deve ser apresentado como 5.05 (505 / 10 ** 2). 122 | * @return value uint8: Retorna o número de casas decimais. 123 | */ 124 | function decimals() public view virtual override returns (uint8) { 125 | return 2; 126 | } 127 | 128 | /** 129 | * @dev Função para incrementar tokens parcialmente bloqueados de uma carteira. 130 | * Somente quem possuir FREEZER_ROLE pode executar. 131 | * @param from address: Carteira origem. 132 | * @param amount uint256: Quantidade de tokens. 133 | */ 134 | function increaseFrozenBalance( 135 | address from, 136 | uint256 amount 137 | ) public whenNotPaused onlyRole(FREEZER_ROLE) { 138 | frozenBalances[from] += amount; 139 | emit FrozenBalance(from, frozenBalances[from]); 140 | } 141 | 142 | /** 143 | * @dev Função para decrementar tokens parcialmente bloqueados de uma carteira. 144 | * Somente quem possuir FREEZER_ROLE pode executar. 145 | * @param from address: Carteira origem. 146 | * @param amount uint256: Quantidade de tokens. 147 | */ 148 | function decreaseFrozenBalance( 149 | address from, 150 | uint256 amount 151 | ) public whenNotPaused onlyRole(FREEZER_ROLE) { 152 | require(frozenBalances[from] >= amount, "Frozen balance is not enough"); 153 | frozenBalances[from] -= amount; 154 | emit FrozenBalance(from, frozenBalances[from]); 155 | } 156 | 157 | /** 158 | * @dev Função para verificar o valor congelado de uma carteira. 159 | * @param wallet address: Carteira que se quer saber o valor congelado. 160 | * @return amount uint256: Quantidade congelada. 161 | */ 162 | function frozenBalanceOf(address wallet) public view returns (uint256) { 163 | return frozenBalances[wallet]; 164 | } 165 | 166 | /** 167 | * @dev Função para emitir tokens para as carteiras permitidas. 168 | * @param to address: Carteira destino. 169 | * @param amount uint256: Quantidade de tokens. 170 | */ 171 | function mint( 172 | address to, 173 | uint256 amount 174 | ) public whenNotPaused onlyRole(MINTER_ROLE) { 175 | uint256 newAllowance = allowance(to, _msgSender()) + amount; 176 | _approve(to, _msgSender(), newAllowance); 177 | _mint(to, amount); 178 | } 179 | 180 | /** 181 | * @dev Função para mover tokens de uma carteira para outra. 182 | * Somente quem possuir MOVER_ROLE pode executar. 183 | * @param from address: Carteira origem. 184 | * @param to address: Carteira destino. 185 | * @param amount uint256: Quantidade de tokens. 186 | */ 187 | function move( 188 | address from, 189 | address to, 190 | uint256 amount 191 | ) public whenNotPaused onlyRole(MOVER_ROLE) { 192 | _transfer(from, to, amount); 193 | } 194 | 195 | /** 196 | * @dev Função para destruir tokens de uma carteira. 197 | * Somente quem possuir MOVER_ROLE pode executar. 198 | * @param from address: Carteira origem. 199 | * @param amount uint256: Quantidade de tokens. 200 | */ 201 | function moveAndBurn( 202 | address from, 203 | uint256 amount 204 | ) public whenNotPaused onlyRole(MOVER_ROLE) { 205 | _transfer(from, address(this), amount); 206 | _burn(address(this), amount); 207 | } 208 | 209 | /** 210 | * @dev Função para transferir tokens para uma carteira. 211 | * @param to address: Carteira destino. 212 | * @param amount uint256: Quantidade de tokens. 213 | * @return value bool: Retorna um valor booleano indicando se a operação foi bem-sucedida. 214 | */ 215 | function transfer( 216 | address to, 217 | uint256 amount 218 | ) public override whenNotPaused returns (bool) { 219 | require( 220 | verifyAccount(_msgSender()), 221 | "Sender account is not authorized" 222 | ); 223 | _transfer(msg.sender, to, amount); 224 | return true; 225 | } 226 | 227 | /** 228 | * @dev Função para definir o valor como allowance de tokens da carteira. 229 | * @param spender address: Carteira para a qual o allowance será configurado. 230 | * @param amount uint256: Quantidade de tokens. 231 | * @return value bool: Retorna um valor booleano indicando se a operação foi bem-sucedida. 232 | */ 233 | function approve( 234 | address spender, 235 | uint256 amount 236 | ) public override whenNotPaused returns (bool) { 237 | require( 238 | verifyAccount(_msgSender()), 239 | "Sender account is not authorized" 240 | ); 241 | _approve(msg.sender, spender, amount); 242 | return true; 243 | } 244 | 245 | /** 246 | * @dev Função para transferir tokens de uma carteira para outra. 247 | * @param from address: Carteira origem. 248 | * @param to address: Carteira destino. 249 | * @param amount uint256: Quantidade de tokens. 250 | * @return value bool: Retorna um valor booleano indicando se a operação foi bem-sucedida. 251 | */ 252 | function transferFrom( 253 | address from, 254 | address to, 255 | uint256 amount 256 | ) public override whenNotPaused returns (bool) { 257 | require( 258 | verifyAccount(from) && verifyAccount(to), 259 | "Either from or to account is not authorized" 260 | ); 261 | 262 | _transfer(from, to, amount); 263 | _approve( 264 | from, 265 | msg.sender, 266 | allowance(from, msg.sender).sub( 267 | amount, 268 | "ERC20: transfer amount exceeds allowance" 269 | ) 270 | ); 271 | 272 | return true; 273 | } 274 | 275 | /** 276 | * @dev Função para atomicamente decrementar o allowance concedido à carteira. 277 | * @param spender address: Carteira para a qual o allowance será decrementado. 278 | * @param subtractedValue uint256: Quantidade de tokens. 279 | * @return value bool: Retorna um valor booleano indicando se a operação foi bem-sucedida. 280 | */ 281 | function decreaseAllowance( 282 | address spender, 283 | uint256 subtractedValue 284 | ) public virtual override whenNotPaused returns (bool) { 285 | require(verifyAccount(_msgSender()), "Account is not authorized"); 286 | _approve( 287 | msg.sender, 288 | spender, 289 | allowance(msg.sender, spender).sub( 290 | subtractedValue, 291 | "ERC20: decreased allowance below zero" 292 | ) 293 | ); 294 | return true; 295 | } 296 | 297 | /** 298 | * @dev Função para atomicamente incrementar o allowance concedido à carteira. 299 | * @param spender address: Carteira para a qual o allowance será incrementado. 300 | * @param addedValue uint256: Quantidade de tokens. 301 | * @return value bool: Retorna um valor booleano indicando se a operação foi bem-sucedida. 302 | */ 303 | function increaseAllowance( 304 | address spender, 305 | uint256 addedValue 306 | ) public virtual override whenNotPaused returns (bool) { 307 | require(verifyAccount(_msgSender()), "Account is not authorized"); 308 | _approve( 309 | msg.sender, 310 | spender, 311 | allowance(msg.sender, spender).add(addedValue) 312 | ); 313 | return true; 314 | } 315 | } 316 | --------------------------------------------------------------------------------