-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathSwapTwoSteps.sol
194 lines (175 loc) · 6.6 KB
/
SwapTwoSteps.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./RealDigital.sol";
import "./RealTokenizado.sol";
/**
* @title SwapTwoSteps
* @dev Este contrato implementa a troca de Real Tokenizado entre dois participantes distintos.
* A troca destrói Real Tokenizado do cliente pagador, transfere Real Digital do participante pagador para o
* participante recebedor e emite Real Tokenizado para o cliente recebedor.
* A operação de swap implementada neste contrato é realizada em duas transações: uma de proposta e outra de aceite.
*/
contract SwapTwoSteps {
RealDigital private CBDC; // Referência ao contrato para que seja efetuada a movimentação de Real Digital.
/**
* @dev Enumeração com as possíveis situações de uma operação de swap.
*/
enum SwapStatus {
PENDING, // Operação de _swap_ registrada, pendente de cancelamento ou execução.
EXECUTED, // Operação de _swap_ executada.
CANCELLED // Operação de _swap_ cancelada.
}
struct SwapProposal {
RealTokenizado tokenSender; // O endereço do contrato de Real Tokenizado do participante pagador.
RealTokenizado tokenReceiver; // O endereço do contrato de Real Tokenizado do participante recebedor.
address sender; // O endereço da wallet do cliente pagador.
address receiver; // O endereço da wallet do cliente recebedor.
uint256 amount; // Quantidade de Reais a ser movimentada.
SwapStatus status; // Situação atual da operação.
uint256 timestamp;
}
uint256 private proposalCounter; // Número da última proposta.
/**
* @dev Mapping de propostas de swap.
*/
mapping(uint256 => SwapProposal) public swapProposals;
/**
* @dev Evento de início do swap.
* @param proposalId uint256: Id da proposta.
* @param senderNumber uint256: CNPJ8 do pagador
* @param receiverNumber uint256: CNPJ8 do recebedor
* @param sender address: Endereço do pagador
* @param receiver address: Endereço do recebedor
* @param amount uint256: Valor
*/
event SwapStarted(
uint256 proposalId,
uint256 senderNumber,
uint256 receiverNumber,
address sender,
address receiver,
uint256 amount
);
/**
* @dev Evento de swap executado.
* @param proposalId uint256: Id da proposta.
* @param senderNumber uint256: CNPJ8 do pagador.
* @param receiverNumber uint256: CNPJ8 do recebedor.
* @param sender address: Endereço do pagador.
* @param receiver address: Endereço do recebedor.
* @param amount uint256: Valor
*/
event SwapExecuted(
uint256 proposalId,
uint256 senderNumber,
uint256 receiverNumber,
address sender,
address receiver,
uint256 amount
);
/**
* @dev Evento de swap cancelado.
* @param proposalId uint256: Id da proposta.
* @param reason string: Razão do cancelamento.
*/
event SwapCancelled(uint256 proposalId, string reason);
/**
* @dev Evento de proposta expirada. A proposta expira em 1 minuto.
* @param proposalId uint256: Id da proposta.
*/
event ExpiredProposal(uint256 proposalId);
/**
* @dev Construtor para instanciar o contrato.
* @param _CBDC address: Endereço do contrato do Real Digital.
*/
constructor(RealDigital _CBDC) {
CBDC = _CBDC;
proposalCounter = 0;
}
/**
* @dev Cria a proposta de swap.
* @param tokenSender address: Endereço do contrato de Real Tokenizado do pagador.
* @param tokenReceiver address: Endereço do contrato de Real Tokenizado do recebedor.
* @param receiver address: Endereço do cliente recebedor.
* @param amount uint256: Valor.
*/
function startSwap(
RealTokenizado tokenSender,
RealTokenizado tokenReceiver,
address receiver,
uint256 amount
) public {
proposalCounter += 1;
swapProposals[proposalCounter] = SwapProposal({
tokenSender: tokenSender,
tokenReceiver: tokenReceiver,
sender: msg.sender,
receiver: receiver,
amount: amount,
status: SwapStatus.PENDING,
timestamp: block.timestamp
});
emit SwapStarted(
proposalCounter,
tokenSender.cnpj8(),
tokenReceiver.cnpj8(),
msg.sender,
receiver,
amount
);
}
/**
* @dev Aceita a proposta de swap, executável apenas pelo recebedor.
* @param proposalId uint256: Id da proposta.
*/
function executeSwap(uint256 proposalId) public {
SwapProposal storage proposal = swapProposals[proposalId];
require(
proposal.receiver == msg.sender,
"Only the receiver can execute the swap."
);
require(
proposal.status == SwapStatus.PENDING,
"Cannot execute swap, status is not PENDING."
);
require(
proposal.timestamp + 7 days > block.timestamp,
"Proposal expired"
);
proposal.tokenSender.burnFrom(proposal.sender, proposal.amount);
CBDC.move(
proposal.tokenSender.reserve(),
proposal.tokenReceiver.reserve(),
proposal.amount
);
proposal.tokenReceiver.mint(proposal.receiver, proposal.amount);
proposal.status = SwapStatus.EXECUTED;
emit SwapExecuted(
proposalId,
proposal.tokenSender.cnpj8(),
proposal.tokenReceiver.cnpj8(),
proposal.sender,
proposal.receiver,
proposal.amount
);
}
/**
* @dev Cancela a proposta.
* Pode ser executada tanto pelo pagador quanto pelo recebedor.
* @param proposalId uint256: Id da proposta
* @param reason string: Razão do cancelamento
*/
function cancelSwap(uint256 proposalId, string memory reason) public {
SwapProposal storage proposal = swapProposals[proposalId];
require(
msg.sender == proposal.sender || msg.sender == proposal.receiver,
"Only the sender or receiver can cancel the swap."
);
require(
proposal.status == SwapStatus.PENDING,
"Cannot cancel swap, status is not PENDING."
);
proposal.status = SwapStatus.CANCELLED;
emit SwapCancelled(proposalId, reason);
}
}