Skip to content

Commit 63f12bc

Browse files
committed
Get rid of pruning logic
1 parent 165e336 commit 63f12bc

File tree

3 files changed

+19
-61
lines changed

3 files changed

+19
-61
lines changed

contracts/libraries/TokenLib.sol

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ library TokenLib {
2525
}
2626

2727
struct InvestorDataStorage {
28-
// List of investors (may not be pruned to remove old investors with current zero balances)
29-
mapping (address => bool) investorListed;
28+
// Index of investors
29+
mapping (address => uint256) investorIndex;
3030
// List of token holders
3131
address[] investors;
32-
// Total number of non-zero token holders
33-
uint256 investorCount;
3432
}
3533

3634
// Emit when Module is archived from the SecurityToken
@@ -163,45 +161,22 @@ library TokenLib {
163161
address _from,
164162
address _to,
165163
uint256 _value,
166-
uint256 _balanceTo,
167-
uint256 _balanceFrom
164+
uint256 _balanceFrom,
165+
uint256 _balanceTo
168166
) public {
169167
if ((_value == 0) || (_from == _to)) {
170168
return;
171169
}
172170
// Check whether receiver is a new token holder
173171
if ((_balanceTo == 0) && (_to != address(0))) {
174-
_investorData.investorCount = (_investorData.investorCount).add(1);
172+
_investorData.investorIndex[_to] = _investorData.investors.length;
173+
_investorData.investors.push(_to);
175174
}
176175
// Check whether sender is moving all of their tokens
177176
if (_value == _balanceFrom) {
178-
_investorData.investorCount = (_investorData.investorCount).sub(1);
179-
}
180-
//Also adjust investor list
181-
if (!_investorData.investorListed[_to] && (_to != address(0))) {
182-
_investorData.investors.push(_to);
183-
_investorData.investorListed[_to] = true;
184-
}
185-
186-
}
187-
188-
/**
189-
* @notice removes addresses with zero balances from the investors list
190-
* @param _investorData is the date related to investor metrics
191-
* NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint
192-
*/
193-
function pruneInvestors(InvestorDataStorage storage _investorData) public {
194-
for (uint256 i = 0; i < _investorData.investors.length; i++) {
195-
if (_investorData.investors[i] == address(0)) {
196-
while(_investorData.investors.length > i) {
197-
if (_investorData.investors[_investorData.investors.length - 1] != address(0)) {
198-
_investorData.investors[i] = _investorData.investors[_investorData.investors.length - 1];
199-
_investorData.investors.length--;
200-
break;
201-
}
202-
_investorData.investors.length--;
203-
}
204-
}
177+
_investorData.investors[_investorData.investorIndex[_from]] = _investorData.investors[_investorData.investors.length - 1];
178+
_investorData.investorIndex[_investorData.investors[_investorData.investorIndex[_from]]] = _investorData.investorIndex[_from];
179+
_investorData.investors.length--;
205180
}
206181
}
207182

contracts/tokens/SecurityToken.sol

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
3838

3939
SemanticVersion securityTokenVersion;
4040

41-
// off-chain data
41+
// off-chain data
4242
string public tokenDetails;
4343

4444
uint8 constant PERMISSION_KEY = 1;
@@ -393,24 +393,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
393393
* @param _value value of transfer
394394
*/
395395
function _adjustInvestorCount(address _from, address _to, uint256 _value) internal {
396-
TokenLib.adjustInvestorCount(investorData, _from, _to, _value, balanceOf(_to), balanceOf(_from));
397-
}
398-
399-
/**
400-
* @notice removes addresses with zero balances from the investors list
401-
* @param _start Index in investor list at which to start removing zero balances
402-
* @param _iters Max number of iterations of the for loop
403-
* NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint
404-
*/
405-
function pruneInvestors(uint256 _start, uint256 _iters) external onlyOwner {
406-
uint iter = Math.min256(_start.add(_iters), investorData.investors.length);
407-
for (uint256 i = _start; i < iter; i++) {
408-
if (balanceOf(investorData.investors[i]) == 0) {
409-
investorData.investorListed[investorData.investors[i]] = false;
410-
investorData.investors[i] = address(0);
411-
}
412-
}
413-
TokenLib.pruneInvestors(investorData);
396+
TokenLib.adjustInvestorCount(investorData, _from, _to, _value, balanceOf(_from), balanceOf(_to));
414397
}
415398

416399
/**
@@ -426,7 +409,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr
426409
* @notice returns the investor count
427410
*/
428411
function getInvestorCount() external view returns(uint256) {
429-
return investorData.investorCount;
412+
return investorData.investors.length;
430413
}
431414

432415
/**

test/o_security_token.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from "./hel
33
import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time";
44
import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall";
55
import { catchRevert } from "./helpers/exceptions";
6-
import {
6+
import {
77
setUpPolymathNetwork,
88
deployGPMAndVerifyed,
99
deployCappedSTOAndVerifyed,
@@ -501,7 +501,7 @@ contract("SecurityToken", accounts => {
501501
it("Should fail to get the total supply -- because checkpoint id is greater than present", async() => {
502502
await catchRevert(
503503
I_SecurityToken.totalSupplyAt.call(50)
504-
);
504+
);
505505
})
506506
});
507507

@@ -855,7 +855,7 @@ contract("SecurityToken", accounts => {
855855
});
856856

857857
it("Should prune investor length", async () => {
858-
await I_SecurityToken.pruneInvestors(0, 10, { from: token_owner });
858+
// await I_SecurityToken.pruneInvestors(0, 10, { from: token_owner });
859859
// Hardcode list of expected accounts based on transfers above
860860

861861
let investors = await I_SecurityToken.getInvestors.call();
@@ -871,7 +871,7 @@ contract("SecurityToken", accounts => {
871871
let balance2 = await I_SecurityToken.balanceOf(account_investor1);
872872
await I_SecurityToken.transfer(account_affiliate1, balance, { from: account_affiliate2});
873873
await I_SecurityToken.transfer(account_affiliate1, balance2, { from: account_investor1});
874-
await I_SecurityToken.pruneInvestors(0, 10, { from: token_owner });
874+
// await I_SecurityToken.pruneInvestors(0, 10, { from: token_owner });
875875
let investors = await I_SecurityToken.getInvestors.call();
876876
let expectedAccounts = [account_affiliate1];
877877
for (let i = 0; i < expectedAccounts.length; i++) {
@@ -893,7 +893,7 @@ contract("SecurityToken", accounts => {
893893
});
894894

895895
describe("Test cases for the Mock TrackedRedeemption", async() => {
896-
896+
897897
it("Should add the tracked redeemption module successfully", async() => {
898898
[I_MockRedemptionManagerFactory] = await deployMockRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0);
899899
let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner });
@@ -959,7 +959,7 @@ contract("SecurityToken", accounts => {
959959
await I_SecurityToken.approve(I_MockRedemptionManager.address, web3.utils.toWei("500"), {from: account_investor1});
960960
// Transfer the tokens to module (Burn)
961961
await I_MockRedemptionManager.transferToRedeem(web3.utils.toWei("500"), { from: account_investor1});
962-
962+
963963
await catchRevert(
964964
// Redeem tokens
965965
I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1})
@@ -1105,4 +1105,4 @@ contract("SecurityToken", accounts => {
11051105
});
11061106
});
11071107

1108-
});
1108+
});

0 commit comments

Comments
 (0)