/
ERC1155Voucher.sol
164 lines (137 loc) · 6.54 KB
/
ERC1155Voucher.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
//SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import {IUserManager} from "../interfaces/IUserManager.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
/// @author Union
/// @title ERC1155Voucher
/// @dev Voucher contract that takes ERC1155 deposits and gives a vouch
contract ERC1155Voucher is Ownable, IERC1155Receiver {
/* -------------------------------------------------------------------
Storage
------------------------------------------------------------------- */
// @notice UserManager contract address
address public immutable USER_MANAGER;
// @notice UserManager staking token eg (DAI)
address public immutable STAKING_TOKEN;
/// @notice Amount of claimable trust
uint256 public trustAmount;
/// @notice Token address to isValid
mapping(address => bool) public isValidToken;
/* -------------------------------------------------------------------
Events
------------------------------------------------------------------- */
/// @notice Fired when a vouch is claimed
/// @param sender Msg sender
event VouchClaimed(address sender);
/// @notice Set trust amount
/// @param amount Trust amount
event SetTrustAmount(uint256 amount);
/// @notice Exit
/// @param amount Amount unstaked
event Exit(uint256 amount);
/// @notice Set is valid
/// @param token Address of token
/// @param isValid Is the token valid
event SetIsValidToken(address token, bool isValid);
/* -------------------------------------------------------------------
Constructor
------------------------------------------------------------------- */
/// @param _userManager UserManager address
/// @param _trustAmount Amount of trust to give
constructor(address _userManager, uint256 _trustAmount) {
address stakingToken = IUserManager(_userManager).stakingToken();
IERC20(stakingToken).approve(_userManager, 0);
IERC20(stakingToken).approve(_userManager, type(uint256).max);
STAKING_TOKEN = stakingToken;
USER_MANAGER = _userManager;
trustAmount = _trustAmount;
}
/* -------------------------------------------------------------------
Setters
------------------------------------------------------------------- */
/// @notice Set the max amount claimable for a token
/// @param amount The trust amount
function setTrustAmount(uint256 amount) external onlyOwner {
trustAmount = amount;
emit SetTrustAmount(amount);
}
/// @notice Set if a token is valid
/// @param token Address of token
/// @param isValid is the token valid
function setIsValid(address token, bool isValid) external onlyOwner {
isValidToken[token] = isValid;
emit SetIsValidToken(token, isValid);
}
/* -------------------------------------------------------------------
Claim Functions
------------------------------------------------------------------- */
function supportsInterface(bytes4 interfaceId) public view returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC165).interfaceId;
}
/// @dev Handles the receipt of a single ERC1155 token type. This function is
/// @param operator The address which initiated the transfer (i.e. msg.sender)
/// @param from The address which previously owned the token
/// @param id The ID of the token being transferred
/// @param value The amount of tokens being transferred
/// @param data Additional data with no specified format
/// @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4) {
require(isValidToken[msg.sender], "!valid token");
_vouchFor(from);
return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
}
/// @dev Handles the receipt of a multiple ERC1155 token types.
/// @param operator The address which initiated the batch transfer (i.e. msg.sender)
/// @param from The address which previously owned the token
/// @param ids An array containing ids of each token being transferred (order and length must match values array)
/// @param values An array containing amounts of each token being transferred (order and length must match ids array)
/// @param data Additional data with no specified format
/// @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4) {
_vouchFor(from);
return bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"));
}
/// @notice Claim vouch from this contract
/// @param acc Account to vouch for
function _vouchFor(address acc) internal {
IUserManager(USER_MANAGER).updateTrust(acc, uint96(trustAmount));
emit VouchClaimed(acc);
}
/* -------------------------------------------------------------------
Union Functions
------------------------------------------------------------------- */
/// @notice Stake into the UserManager contract
function stake() external {
uint256 balance = IERC20(STAKING_TOKEN).balanceOf(address(this));
IUserManager(USER_MANAGER).stake(uint96(balance));
}
/// @notice Exit. Unstake the max unstakable from the userManager
function exit() external onlyOwner {
(, uint96 stakeAmount, uint96 locked, , , ) = IUserManager(USER_MANAGER).stakers(address(this));
uint256 maxUnstake = uint256(stakeAmount - locked);
IUserManager(USER_MANAGER).unstake(uint96(maxUnstake));
emit Exit(maxUnstake);
}
/// @notice Transfer ERC20 tokens
/// @param token Token address
/// @param to Token receiver
/// @param amount Amount of tokens to send
function transferERC20(address token, address to, uint256 amount) external onlyOwner {
IERC20(token).transfer(to, amount);
}
}