-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
SingatureReplay.sol
79 lines (66 loc) · 3.12 KB
/
SingatureReplay.sol
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
// Exemplo de erro de gerenciamento de permissões
contract SigReplay is ERC20 {
address public signer;
// Construtor: inicializa o nome e o código do token
constructor() ERC20("SigReplay", "Replay") {
signer = msg.sender;
}
/**
* Função de construção com vulnerabilidade de reentrada
* para: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
* quantidade: 1000
* Assinatura: 0x5a4f1ad4d8bd6b5582e658087633230d9810a0b7b8afa791e3f94cc38947f6cb1069519caf5bba7b975df29cbfdb4ada355027589a989435bf88e825841452f61b
*/
function badMint(address to, uint amount, bytes memory signature) public {
bytes32 _msgHash = toEthSignedMessageHash(getMessageHash(to, amount));
require(verify(_msgHash, signature), "Invalid Signer!");
_mint(to, amount);
}
/**
* Combinar o endereço 'to' (tipo address) e o valor 'amount' (tipo uint256) para formar a mensagem msgHash
* to: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
* amount: 1000
* msgHash correspondente: 0xb4a4ba10fbd6886a312ec31c54137f5714ddc0e93274da8746a36d2fa96768be
*/
function getMessageHash(address to, uint256 amount) public pure returns(bytes32){
return keccak256(abi.encodePacked(to, amount));
}
/**
* @dev Obter mensagem assinada do Ethereum
* `hash`: Hash da mensagem
* Segue o padrão de assinatura do Ethereum: https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* E também `EIP191`: https://eips.ethereum.org/EIPS/eip-191`
* Adiciona o campo "\x19Ethereum Signed Message:\n32" para evitar que a assinatura seja de uma transação executável.
*/
function toEthSignedMessageHash(bytes32 hash) public pure returns (bytes32) {
// 32 é o comprimento em bytes do hash,
// aplicado pela assinatura de tipo acima
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
// ECDSA verificação
function verify(bytes32 _msgHash, bytes memory _signature) public view returns (bool){
return ECDSA.recover(_msgHash, _signature) == signer;
}
// Registre os endereços já mintados
function goodMint(address to, uint amount, bytes memory signature) public {
bytes32 _msgHash = toEthSignedMessageHash(getMessageHash(to, amount));
require(verify(_msgHash, signature), "Invalid Signer!");
// Verifique se este endereço já foi mintado
require(!mintedAddress[to], "Already minted");
// Registre os endereços que foram mintados
mintedAddress[to] = true;
_mint(to, amount);
}
uint nonce;
function nonceMint(address to, uint amount, bytes memory signature) public {
bytes32 _msgHash = toEthSignedMessageHash(keccak256(abi.encodePacked(to, amount, nonce, block.chainid)));
require(verify(_msgHash, signature), "Invalid Signer!");
_mint(to, amount);
nonce++;
}
}