Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation for reverting stake and redemption #31

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e5e9239
test: Protocol.js deploy and add core
benjaminbollen Nov 29, 2017
fbbcc35
Adding truffle and ethereumjs-testrpc in dev dependencies
Nov 29, 2017
6acf885
test: simple gas measurement tracker and apply to integration tests
benjaminbollen Nov 29, 2017
84d30a8
test: register STP
benjaminbollen Nov 30, 2017
b4db70a
test: Task Separation & Indentation Update
Nov 30, 2017
159a9e2
test: Initialize Transfer to ST' Contract Address
Nov 30, 2017
cc23267
test: Protocol.js propose and registerd branded token
Nov 30, 2017
8316620
test: Protocol.js Adding registerUtilitytoken for branded token
Nov 30, 2017
5c11af9
Test: Protocol.js changing the call method to actual call
Nov 30, 2017
e7967d2
test: Added Event Decoder Library for Events Assert
Nov 30, 2017
08c96fa
test: stake for ST Prime
benjaminbollen Nov 30, 2017
9ccb894
test: Member details in global scope for everyone to use
Nov 30, 2017
8e4290c
Test: Protocol.js changing the validation based on events raised thro…
Nov 30, 2017
b3f52a2
test: Protocol stake ST for ST Prime
benjaminbollen Dec 1, 2017
7971f95
test: Member details in global scope for everyone to use
Nov 30, 2017
3124f6b
test: Basic Skeleton for Stake and Mint
Dec 1, 2017
16809b4
contracts: revertStaking
benjaminbollen Dec 3, 2017
b9f0e5a
contracts: OpenSTUtility.revertRedemption. Addresses #27
benjaminbollen Dec 4, 2017
bce21de
contracts: OpenSTValue.revertUnstaking
benjaminbollen Dec 4, 2017
8700e8d
Merge branch 'master' into benjaminbollen/gh27/revert
benjaminbollen Dec 6, 2017
e2842f0
Merge branch 'master' into benjaminbollen/gh27/revert
benjaminbollen Dec 6, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 71 additions & 60 deletions contracts/OpenSTUtility.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,15 @@ contract OpenSTUtility is Hasher, OpsManaged {
address _staker, address _beneficiary, uint256 _amountST, uint256 _amountUT, uint256 _expirationHeight);
event ProcessedMint(bytes32 indexed _uuid, bytes32 indexed _stakingIntentHash, address _token,
address _staker, address _beneficiary, uint256 _amount);
event RevertedMint(bytes32 indexed _uuid, bytes32 indexed _stakingIntentHash, address _staker,
address _beneficiary, uint256 _amountUT);
event RedemptionIntentDeclared(bytes32 indexed _uuid, bytes32 indexed _redemptionIntentHash,
address _token, address _redeemer, uint256 _nonce, uint256 _amount, uint256 _unlockHeight,
uint256 _chainIdValue);
event ProcessedRedemption(bytes32 indexed _uuid, bytes32 indexed _redemptionIntentHash, address _token,
address _redeemer, uint256 _amount);
event RevertedRedemption(bytes32 indexed _uuid, bytes32 indexed _redemptionIntentHash,
address _redeemer, uint256 _amountUT);

/*
* Constants
Expand Down Expand Up @@ -393,6 +397,36 @@ contract OpenSTUtility is Hasher, OpsManaged {
return tokenAddress;
}

function revertMinting(
bytes32 _stakingIntentHash)
external
returns (
bytes32 uuid,
address staker,
address beneficiary,
uint256 amount)
{
require(_stakingIntentHash != "");

Mint storage mint = mints[_stakingIntentHash];

// require that the mint has expired and that the staker has not
// processed the minting, ie mint has not been deleted
require(mint.expirationHeight > 0);
require(mint.expirationHeight <= block.number);

uuid = mint.uuid;
amount = mint.amount;
staker = mint.staker;
beneficiary = mint.beneficiary;

delete mints[_stakingIntentHash];

RevertedMint(uuid, _stakingIntentHash, staker, beneficiary, amount);

return (uuid, staker, beneficiary, amount);
}

/// @dev redeemer must set an allowance for the branded token with OpenSTUtility
/// as the spender so that the branded token can be taken into escrow by OpenSTUtility
/// note: for STPrime, call OpenSTUtility.redeemSTPrime as a payable function
Expand Down Expand Up @@ -514,6 +548,43 @@ contract OpenSTUtility is Hasher, OpsManaged {
return tokenAddress;
}

function revertRedemption(
bytes32 _redemptionIntentHash)
external
returns (
bytes32 uuid,
address redeemer,
uint256 amountUT)
{
require(_redemptionIntentHash != "");

Redemption storage redemption = redemptions[_redemptionIntentHash];

// require that the redemption is unlocked and exists
require(redemption.unlockHeight > 0);
require(redemption.unlockHeight <= block.number);

uuid = redemption.uuid;
amountUT = redemption.amountUT;
redeemer = redemption.redeemer;

if (redemption.uuid == uuidSTPrime) {
// transfer throws if insufficient funds
redeemer.transfer(amountUT);
} else {
EIP20Interface token = EIP20Interface(registeredTokens[redemption.uuid].token);

require(token.transfer(redemption.redeemer, redemption.amountUT));
}

delete redemptions[_redemptionIntentHash];

// fire event
RevertedRedemption(uuid, _redemptionIntentHash, redeemer, amountUT);

return (uuid, redeemer, amountUT);
}

/*
* Public view functions
*/
Expand All @@ -530,64 +601,4 @@ contract OpenSTUtility is Hasher, OpsManaged {
address(registeredToken.token),
registeredToken.registrar);
}

/*
* Operation functions
*/
/// @dev TODO: add events to trigger for each action
function addNameReservation(
bytes32 _hashName,
address _requester)
public
onlyAdminOrOps
returns (bool /* success */)
{
address requester = nameReservation[_hashName];
if (requester == _requester) return true;
if (requester == address(0)) {
nameReservation[_hashName] = _requester;
return true;
}
return false;
}

function setSymbolRoute(
bytes32 _hashSymbol,
address _token)
public
onlyAdminOrOps
returns (bool /* success */)
{
address token = symbolRoute[_hashSymbol];
if (token == _token) return true;
if (token == address(0)) {
symbolRoute[_hashSymbol] = _token;
return true;
}
return false;
}

function removeNameReservation(
bytes32 _hashName)
public
onlyAdminOrOps
returns (bool /* success */)
{
require(nameReservation[_hashName] != address(0));

delete nameReservation[_hashName];
return true;
}

function removeSymbolRoute(
bytes32 _hashSymbol)
public
onlyAdminOrOps
returns (bool /* success */)
{
require(symbolRoute[_hashSymbol] != address(0));

delete symbolRoute[_hashSymbol];
return true;
}
}
65 changes: 65 additions & 0 deletions contracts/OpenSTValue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,14 @@ contract OpenSTValue is OpsManaged, Hasher {
uint256 _chainIdUtility);
event ProcessedStake(bytes32 indexed _uuid, bytes32 indexed _stakingIntentHash,
address _stake, address _staker, uint256 _amountST, uint256 _amountUT);
event RevertedStake(bytes32 indexed _uuid, bytes32 indexed _stakingIntentHash,
address _staker, uint256 _amountST, uint256 _amountUT);
event RedemptionIntentConfirmed(bytes32 indexed _uuid, bytes32 _redemptionIntentHash,
address _redeemer, uint256 _amountST, uint256 _amountUT, uint256 _expirationHeight);
event ProcessedUnstake(bytes32 indexed _uuid, bytes32 indexed _redemptionIntentHash,
address stake, address _redeemer, uint256 _amountST);
event RevertedUnstake(bytes32 indexed _uuid, bytes32 indexed _redemptionIntentHash,
address _redeemer, uint256 _amountST);

/*
* Constants
Expand Down Expand Up @@ -238,6 +242,38 @@ contract OpenSTValue is OpsManaged, Hasher {
return stakeAddress;
}

function revertStaking(
bytes32 _stakingIntentHash)
external
returns (
bytes32 uuid,
uint256 amountST,
address staker)
{
require(_stakingIntentHash != "");

Stake storage stake = stakes[_stakingIntentHash];

// require that the stake is unlocked and exists
require(stake.unlockHeight > 0);
require(stake.unlockHeight <= block.number);

assert(valueToken.balanceOf(address(this)) >= stake.amountST);
// revert the amount that was intended to be staked back to staker
require(valueToken.transfer(stake.staker, stake.amountST));

uuid = stake.uuid;
amountST = stake.amountST;
staker = stake.staker;

RevertedStake(stake.uuid, _stakingIntentHash, stake.staker,
stake.amountST, stake.amountUT);

delete stakes[_stakingIntentHash];

return (uuid, amountST, staker);
}

function confirmRedemptionIntent(
bytes32 _uuid,
address _redeemer,
Expand Down Expand Up @@ -324,6 +360,35 @@ contract OpenSTValue is OpsManaged, Hasher {
return stakeAddress;
}

function revertUnstaking(
bytes32 _redemptionIntentHash)
external
onlyRegistrar
returns (
bytes32 uuid,
address redeemer,
uint256 amountST)
{
require(_redemptionIntentHash != "");

Unstake storage unstake = unstakes[_redemptionIntentHash];

// require that the unstake has expired and that the redeemer has not
// processed the unstaking, ie unstake has not been deleted
require(unstake.expirationHeight > 0);
require(unstake.expirationHeight <= block.number);

uuid = unstake.uuid;
redeemer = unstake.redeemer;
amountST = unstake.amountST;

delete unstakes[_redemptionIntentHash];

RevertedUnstake(uuid, _redemptionIntentHash, redeemer, amountST);

return (uuid, redeemer, amountST);
}

/*
* Public view functions
*/
Expand Down
109 changes: 0 additions & 109 deletions test/OpenSTUtility.js
Original file line number Diff line number Diff line change
Expand Up @@ -472,113 +472,4 @@ contract('OpenSTUtility', function(accounts) {
})
})
})

/**
* note: code is removed from contracts as unused and space needed for protocol completion
TODO: remove once certain no such logic is required

describe('AddNameReservation', async () => {
before(async () => {
contracts = await OpenSTUtility_utils.deployOpenSTUtility(artifacts, accounts);
openSTUtility = contracts.openSTUtility;
await openSTUtility.setAdminAddress(accounts[2]);
})

it('fails to add by non-adminOrOps', async () => {
await Utils.expectThrow(openSTUtility.addNameReservation(hashName, requester));
})

it('successfully adds', async () => {
assert.equal(await openSTUtility.nameReservation.call(hashName), 0);
assert.equal(await openSTUtility.addNameReservation.call(hashName, requester, { from: accounts[2] }), true);
await openSTUtility.addNameReservation(hashName, requester, { from: accounts[2] });

assert.equal(await openSTUtility.nameReservation.call(hashName), requester);
})

it('fails to add if exists with a different requester', async () => {
await openSTUtility.addNameReservation.call(hashName, accounts[0], { from: accounts[2] });

assert.notEqual(await openSTUtility.nameReservation.call(hashName), accounts[0]);
assert.equal(await openSTUtility.nameReservation.call(hashName), requester);
})
})

describe('SetSymbolRoute', async () => {
before(async () => {
contracts = await OpenSTUtility_utils.deployOpenSTUtility(artifacts, accounts);
openSTUtility = contracts.openSTUtility;
await openSTUtility.setAdminAddress(accounts[2]);
})

it('fails to set by non-adminOrOps', async () => {
await Utils.expectThrow(openSTUtility.setSymbolRoute(hashSymbol, token));
})

it('successfully sets', async () => {
assert.equal(await openSTUtility.symbolRoute.call(hashSymbol), 0);
assert.equal(await openSTUtility.setSymbolRoute.call(hashSymbol, token, { from: accounts[2] }), true);
await openSTUtility.setSymbolRoute(hashSymbol, token, { from: accounts[2] });

assert.equal(await openSTUtility.symbolRoute.call(hashSymbol), token);
})

it('fails to set if exists with a different token', async () => {
await openSTUtility.setSymbolRoute.call(hashSymbol, accounts[0], { from: accounts[2] });

assert.notEqual(await openSTUtility.symbolRoute.call(hashSymbol), accounts[0]);
assert.equal(await openSTUtility.symbolRoute.call(hashSymbol), token);
})
})

describe('RemoveNameReservation', async () => {
before(async () => {
contracts = await OpenSTUtility_utils.deployOpenSTUtility(artifacts, accounts);
openSTUtility = contracts.openSTUtility;
await openSTUtility.setAdminAddress(accounts[2]);
await openSTUtility.addNameReservation(hashName, requester, { from: accounts[2] });
})

it('fails to remove by non-adminOrOps', async () => {
await Utils.expectThrow(openSTUtility.removeNameReservation(hashName));
})

it('successfully removes', async () => {
assert.equal(await openSTUtility.nameReservation.call(hashName), requester);
assert.equal(await openSTUtility.removeNameReservation.call(hashName, { from: accounts[2] }), true);
await openSTUtility.removeNameReservation(hashName, { from: accounts[2] })

assert.equal(await openSTUtility.nameReservation.call(hashName), 0);
})

it('fails to remove if it does not exist', async () => {
await Utils.expectThrow(openSTUtility.removeNameReservation(hashName, { from: accounts[2] }));
})
})

describe('removeSymbolRoute', async () => {
before(async () => {
contracts = await OpenSTUtility_utils.deployOpenSTUtility(artifacts, accounts);
openSTUtility = contracts.openSTUtility;
await openSTUtility.setAdminAddress(accounts[2]);
await openSTUtility.setSymbolRoute(hashSymbol, token, { from: accounts[2] });
})

it('fails to remove by non-adminOrOps', async () => {
await Utils.expectThrow(openSTUtility.removeSymbolRoute(hashSymbol));
})

it('successfully removes', async () => {
assert.equal(await openSTUtility.symbolRoute.call(hashSymbol), token);
assert.equal(await openSTUtility.removeSymbolRoute.call(hashSymbol, { from: accounts[2] }), true);
await openSTUtility.removeSymbolRoute(hashSymbol, { from: accounts[2] })

assert.equal(await openSTUtility.symbolRoute.call(hashSymbol), 0);
})

it('fails to remove if it does not exist', async () => {
await Utils.expectThrow(openSTUtility.removeSymbolRoute(hashSymbol, { from: accounts[2] }));
})
})
*/
})
1 change: 1 addition & 0 deletions test/OpenSTValue_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ module.exports.checkStakingIntentDeclaredEvent = (event, _uuid, _staker, _staker
assert.equal(event.args._chainIdUtility, _chainIdUtility);
}


module.exports.checkStakingIntentDeclaredEventProtocol = (formattedDecodedEvents, _uuid, _staker, _stakerNonce, _beneficiary,
_amountST, _amountUT, _chainIdUtility) => {

Expand Down
Loading