Skip to content

Commit 42e4a78

Browse files
authored
Optimise GTM (#433)
- Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset. - Add address[] public investors to record a list of all addresses that have been added to the whitelist - Fix for when allowAllWhitelistIssuances is FALSE - Clearer logic around toTime, fromTime & expiryTime - Make GTM a Proxy based implementation to reduce deployment gas costs
1 parent cd04aa3 commit 42e4a78

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+975
-1449
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file.
1313
* Added `getTokensSoldByTier` to return sold (not minted during finalisation) tokens in each tier to USDTSTO.
1414
* Removed individual mappings for tier data removed in UDSTSTO.
1515

16+
# GeneralTransferManager
17+
* Add an Offset that can be used to move all from & to dates forwards or backwards by a fixed offset.
18+
* Add `address[] public investors` to record a list of all addresses that have been added to the whitelist (`getInvestors`)
19+
* Fix for when `allowAllWhitelistIssuances` is FALSE
20+
* Make GTM a Proxy based implementation to reduce deployment gas costs
21+
1622
##Changed
1723
* `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore.
1824

contracts/modules/Checkpoint/DividendCheckpoint.sol

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
pragma solidity ^0.4.24;
99

1010
import "./ICheckpoint.sol";
11+
import "./DividendCheckpointStorage.sol";
1112
import "../Module.sol";
1213
import "../../interfaces/ISecurityToken.sol";
1314
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
@@ -17,43 +18,9 @@ import "openzeppelin-solidity/contracts/math/Math.sol";
1718
* @title Checkpoint module for issuing ether dividends
1819
* @dev abstract contract
1920
*/
20-
contract DividendCheckpoint is ICheckpoint, Module {
21+
contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module {
2122
using SafeMath for uint256;
2223

23-
uint256 public EXCLUDED_ADDRESS_LIMIT = 50;
24-
bytes32 public constant DISTRIBUTE = "DISTRIBUTE";
25-
bytes32 public constant MANAGE = "MANAGE";
26-
bytes32 public constant CHECKPOINT = "CHECKPOINT";
27-
28-
struct Dividend {
29-
uint256 checkpointId;
30-
uint256 created; // Time at which the dividend was created
31-
uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass
32-
uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer -
33-
// set to very high value to bypass
34-
uint256 amount; // Dividend amount in WEI
35-
uint256 claimedAmount; // Amount of dividend claimed so far
36-
uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this)
37-
bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend
38-
uint256 dividendWithheld;
39-
uint256 dividendWithheldReclaimed;
40-
mapping (address => bool) claimed; // List of addresses which have claimed dividend
41-
mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends
42-
bytes32 name; // Name/title - used for identification
43-
}
44-
45-
// List of all dividends
46-
Dividend[] public dividends;
47-
48-
// List of addresses which cannot claim dividends
49-
address[] public excluded;
50-
51-
// Mapping from address to withholding tax as a percentage * 10**16
52-
mapping (address => uint256) public withholdingTax;
53-
54-
// Total amount of ETH withheld per investor
55-
mapping (address => uint256) public investorWithheld;
56-
5724
event SetDefaultExcludedAddresses(address[] _excluded, uint256 _timestamp);
5825
event SetWithholding(address[] _investors, uint256[] _withholding, uint256 _timestamp);
5926
event SetWithholdingFixed(address[] _investors, uint256 _withholding, uint256 _timestamp);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
pragma solidity ^0.4.24;
2+
3+
/**
4+
* @title Holds the storage variable for the DividendCheckpoint modules (i.e ERC20, Ether)
5+
* @dev abstract contract
6+
*/
7+
contract DividendCheckpointStorage {
8+
9+
uint256 public EXCLUDED_ADDRESS_LIMIT = 50;
10+
bytes32 public constant DISTRIBUTE = "DISTRIBUTE";
11+
bytes32 public constant MANAGE = "MANAGE";
12+
bytes32 public constant CHECKPOINT = "CHECKPOINT";
13+
14+
struct Dividend {
15+
uint256 checkpointId;
16+
uint256 created; // Time at which the dividend was created
17+
uint256 maturity; // Time after which dividend can be claimed - set to 0 to bypass
18+
uint256 expiry; // Time until which dividend can be claimed - after this time any remaining amount can be withdrawn by issuer -
19+
// set to very high value to bypass
20+
uint256 amount; // Dividend amount in WEI
21+
uint256 claimedAmount; // Amount of dividend claimed so far
22+
uint256 totalSupply; // Total supply at the associated checkpoint (avoids recalculating this)
23+
bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend
24+
uint256 dividendWithheld;
25+
uint256 dividendWithheldReclaimed;
26+
mapping (address => bool) claimed; // List of addresses which have claimed dividend
27+
mapping (address => bool) dividendExcluded; // List of addresses which cannot claim dividends
28+
bytes32 name; // Name/title - used for identification
29+
}
30+
31+
// List of all dividends
32+
Dividend[] public dividends;
33+
34+
// List of addresses which cannot claim dividends
35+
address[] public excluded;
36+
37+
// Mapping from address to withholding tax as a percentage * 10**16
38+
mapping (address => uint256) public withholdingTax;
39+
40+
// Total amount of ETH withheld per investor
41+
mapping (address => uint256) public investorWithheld;
42+
43+
}

contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
pragma solidity ^0.4.24;
22

33
import "./DividendCheckpoint.sol";
4+
import "./ERC20DividendCheckpointStorage.sol";
45
import "../../interfaces/IOwnable.sol";
56
import "../../interfaces/IERC20.sol";
67

78
/**
89
* @title Checkpoint module for issuing ERC20 dividends
910
*/
10-
contract ERC20DividendCheckpoint is DividendCheckpoint {
11+
contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendCheckpoint {
1112
using SafeMath for uint256;
1213

13-
// Mapping to token address for each dividend
14-
mapping (uint256 => address) public dividendTokens;
1514
event ERC20DividendDeposited(
1615
address indexed _depositor,
1716
uint256 _checkpointId,
@@ -68,8 +67,8 @@ contract ERC20DividendCheckpoint is DividendCheckpoint {
6867
address _token,
6968
uint256 _amount,
7069
bytes32 _name
71-
)
72-
external
70+
)
71+
external
7372
withPerm(MANAGE)
7473
{
7574
createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name);
@@ -133,16 +132,16 @@ contract ERC20DividendCheckpoint is DividendCheckpoint {
133132
* @param _name Name/Title for identification
134133
*/
135134
function createDividendWithCheckpointAndExclusions(
136-
uint256 _maturity,
137-
uint256 _expiry,
138-
address _token,
139-
uint256 _amount,
140-
uint256 _checkpointId,
135+
uint256 _maturity,
136+
uint256 _expiry,
137+
address _token,
138+
uint256 _amount,
139+
uint256 _checkpointId,
141140
address[] _excluded,
142141
bytes32 _name
143-
)
142+
)
144143
public
145-
withPerm(MANAGE)
144+
withPerm(MANAGE)
146145
{
147146
_createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name);
148147
}
@@ -158,15 +157,15 @@ contract ERC20DividendCheckpoint is DividendCheckpoint {
158157
* @param _name Name/Title for identification
159158
*/
160159
function _createDividendWithCheckpointAndExclusions(
161-
uint256 _maturity,
162-
uint256 _expiry,
163-
address _token,
164-
uint256 _amount,
165-
uint256 _checkpointId,
160+
uint256 _maturity,
161+
uint256 _expiry,
162+
address _token,
163+
uint256 _amount,
164+
uint256 _checkpointId,
166165
address[] _excluded,
167166
bytes32 _name
168-
)
169-
internal
167+
)
168+
internal
170169
{
171170
ISecurityToken securityTokenInstance = ISecurityToken(securityToken);
172171
require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded");
@@ -210,7 +209,7 @@ contract ERC20DividendCheckpoint is DividendCheckpoint {
210209
}
211210

212211
/**
213-
* @notice Emits the ERC20DividendDeposited event.
212+
* @notice Emits the ERC20DividendDeposited event.
214213
* Seperated into a different function as a workaround for stack too deep error
215214
*/
216215
function _emitERC20DividendDepositedEvent(

contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
pragma solidity ^0.4.24;
22

3-
import "./ERC20DividendCheckpoint.sol";
3+
import "../../proxy/ERC20DividendCheckpointProxy.sol";
44
import "../ModuleFactory.sol";
55

66
/**
77
* @title Factory for deploying ERC20DividendCheckpoint module
88
*/
99
contract ERC20DividendCheckpointFactory is ModuleFactory {
1010

11+
address public logicContract;
12+
1113
/**
1214
* @notice Constructor
1315
* @param _polyAddress Address of the polytoken
1416
* @param _setupCost Setup cost of the module
1517
* @param _usageCost Usage cost of the module
1618
* @param _subscriptionCost Subscription cost of the module
1719
*/
18-
constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public
20+
constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public
1921
ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost)
2022
{
2123
version = "1.0.0";
@@ -24,6 +26,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory {
2426
description = "Create ERC20 dividends for token holders at a specific checkpoint";
2527
compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0));
2628
compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0));
29+
logicContract = _logicContract;
2730
}
2831

2932
/**
@@ -33,7 +36,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory {
3336
function deploy(bytes /* _data */) external returns(address) {
3437
if (setupCost > 0)
3538
require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance");
36-
address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken));
39+
address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, address(polyToken), logicContract);
3740
/*solium-disable-next-line security/no-block-members*/
3841
emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now);
3942
return erc20DividendCheckpoint;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
pragma solidity ^0.4.24;
2+
3+
/**
4+
* @title It holds the storage variables related to ERC20DividendCheckpoint module
5+
*/
6+
contract ERC20DividendCheckpointStorage {
7+
8+
// Mapping to token address for each dividend
9+
mapping (uint256 => address) public dividendTokens;
10+
11+
}

contracts/modules/Checkpoint/EtherDividendCheckpoint.sol

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import "../../interfaces/IOwnable.sol";
88
*/
99
contract EtherDividendCheckpoint is DividendCheckpoint {
1010
using SafeMath for uint256;
11+
1112
event EtherDividendDeposited(
1213
address indexed _depositor,
1314
uint256 _checkpointId,
@@ -56,7 +57,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint {
5657
uint256 _expiry,
5758
uint256 _checkpointId,
5859
bytes32 _name
59-
)
60+
)
6061
external
6162
payable
6263
withPerm(MANAGE)
@@ -76,7 +77,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint {
7677
uint256 _expiry,
7778
address[] _excluded,
7879
bytes32 _name
79-
)
80+
)
8081
public
8182
payable
8283
withPerm(MANAGE)
@@ -94,10 +95,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint {
9495
* @param _name Name/title for identification
9596
*/
9697
function createDividendWithCheckpointAndExclusions(
97-
uint256 _maturity,
98-
uint256 _expiry,
99-
uint256 _checkpointId,
100-
address[] _excluded,
98+
uint256 _maturity,
99+
uint256 _expiry,
100+
uint256 _checkpointId,
101+
address[] _excluded,
101102
bytes32 _name
102103
)
103104
public
@@ -116,12 +117,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint {
116117
* @param _name Name/title for identification
117118
*/
118119
function _createDividendWithCheckpointAndExclusions(
119-
uint256 _maturity,
120-
uint256 _expiry,
121-
uint256 _checkpointId,
122-
address[] _excluded,
120+
uint256 _maturity,
121+
uint256 _expiry,
122+
uint256 _checkpointId,
123+
address[] _excluded,
123124
bytes32 _name
124-
)
125+
)
125126
internal
126127
{
127128
require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded");
@@ -169,7 +170,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint {
169170
*/
170171
function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal {
171172
(uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee);
172-
_dividend.claimed[_payee] = true;
173+
_dividend.claimed[_payee] = true;
173174
uint256 claimAfterWithheld = claim.sub(withheld);
174175
if (claimAfterWithheld > 0) {
175176
/*solium-disable-next-line security/no-send*/

contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
pragma solidity ^0.4.24;
22

3-
import "./EtherDividendCheckpoint.sol";
3+
import "../../proxy/EtherDividendCheckpointProxy.sol";
44
import "../ModuleFactory.sol";
55

66
/**
77
* @title Factory for deploying EtherDividendCheckpoint module
88
*/
99
contract EtherDividendCheckpointFactory is ModuleFactory {
1010

11+
address public logicContract;
12+
1113
/**
1214
* @notice Constructor
1315
* @param _polyAddress Address of the polytoken
1416
* @param _setupCost Setup cost of the module
1517
* @param _usageCost Usage cost of the module
1618
* @param _subscriptionCost Subscription cost of the module
1719
*/
18-
constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public
20+
constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public
1921
ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost)
2022
{
2123
version = "1.0.0";
@@ -24,6 +26,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory {
2426
description = "Create ETH dividends for token holders at a specific checkpoint";
2527
compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0));
2628
compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0));
29+
logicContract = _logicContract;
2730
}
2831

2932
/**
@@ -33,7 +36,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory {
3336
function deploy(bytes /* _data */) external returns(address) {
3437
if(setupCost > 0)
3538
require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance");
36-
address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken));
39+
address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, address(polyToken), logicContract);
3740
/*solium-disable-next-line security/no-block-members*/
3841
emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now);
3942
return ethDividendCheckpoint;

0 commit comments

Comments
 (0)