Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
test bearer siganture
Browse files Browse the repository at this point in the history
  • Loading branch information
Christophe Le Bars committed Jul 20, 2018
1 parent 52b2a69 commit 27b4b87
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 44 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# The Rouge Project - beta code factory and campaign contracts to be used with the RGE token

The Rouge token [RGE] has be audited but not yet the factory. Please do your own due diligences if you
WARNING: The Rouge token [RGE] has been audited but not yet the factory. Please do your own due diligences if you
decide to use this code on the Ethereum mainnet. You may lose your RGE deposit.

WARNING : this NON AUDITED code. Use on testnet or with extreme caution.
WARNING : this is NON AUDITED code. Use on testnet or with extreme caution.

The project use the truffle framework (http://truffleframework.com/)

Expand All @@ -22,7 +22,23 @@ The project use the truffle framework (http://truffleframework.com/)
truffle test
```

That's all for now...
## Creating a campaign :

1. You should have a minimum of RGE tokens on the Ethereum address creating the campaign (issuer) :

mim RGE = number of notes to be issued * tare price.

The tare price is now set to be 0.1 RGE (as per the white paper, tare will be raised to 1 RGE as usage of
the network grow).

2. Call the function newCampaign(issuance, deposit)

issuance = number of notes to be created/issued

deposit = RGE that you move to the campaign as deposit (should equal or more than mim RGE)

3. Enjoy :)


### Licensed under GNU AFFERO GENERAL PUBLIC LICENSE v3

Expand Down
2 changes: 1 addition & 1 deletion contracts/RougeFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ contract RougeFactory is RougeRegistry {
function createCampaign(address _issuer, uint32 _issuance, uint256 _tokens) public {

SimpleRougeCampaign c = new SimpleRougeCampaign(_issuer, _issuance, rge, tare, this);

// XXX no need to check rge set ? transfer would revert ...
rge.transfer(c, _tokens); // transfer tokens to the campaign contract ...

Expand Down
51 changes: 32 additions & 19 deletions contracts/SimpleRougeCampaign.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ contract SimpleRougeCampaign {

// still possible to send RGE post creation, before issuing the campaign
uint256 rgeBalance = rge.balanceOf(this);
require(rgeBalance > issuance * tare);
require(rgeBalance >= issuance * tare);

// TODO XXX limit expiration to now + 3 months ?

name = _name;
campaignIssued = true;
campaignExpiration = _campaignExpiration;
Expand Down Expand Up @@ -121,37 +123,48 @@ contract SimpleRougeCampaign {
require(hasNote(_bearer));
return redemptionRegister[_bearer];
}


event Redeem(address indexed bearer);

function redeemNote(address _bearer) CampaignOpen private returns (bool success) {
require(_bearer != issuer);
require(!hasRedeemed(_bearer));
redeemed += 1;
redemptionRegister[_bearer] = true;
emit Redeem(_bearer);
return true;
}

function useNote() CampaignOpen public returns (bool success) {
require(msg.sender != issuer); /* SI_10 issuer is excluded for now to simplify tests */

/* TODO global contract expiration test => if expired change state */

/* TODO send to checkout contract => return always ok in these tests (could put conditions on pos/target)
require approval from issuer
*/

// web3.eth.sign compat prefix
function prefixed(bytes32 hash) internal pure returns (bytes32) {
return keccak256("\x19Ethereum Signed Message:\n32", hash);
}

// _hash is any hashed msg agreed between issuer and bearer
// WARNING: replay protection not implemented at protocol level
function acceptRedemption(address _bearer, bytes32 _hash, uint8 v, bytes32 r, bytes32 s)
CampaignOpen onlyBy(issuer) public returns (bool success) {

bytes32 message = prefixed(_hash);

require(ecrecover(message, v, r, s) == _bearer);

return redeemNote(_bearer);
}

function confirmRedemption(bytes32 _hashmsg, uint8 v, bytes32 r, bytes32 s) CampaignOpen public returns (bool success) {
require(ecrecover(_hashmsg, v, r, s) == issuer);
return redeemNote(msg.sender);
}

/* function letsBurn(uint256 _value) onlyBy(issuer) public { */
/* rge.burn(_value); */
/* } */


function kill() onlyBy(issuer) public {

// burn the tare

rge.burn(tare * (issuance - redeemed));
// burn the tare for unredeemed notes if campaign has started

if (campaignIssued) {
rge.burn(tare * (issuance - redeemed));
}

// transfer all remaining tokens and ETH to the issuer

uint256 rgeBalance = rge.balanceOf(this);
Expand Down
97 changes: 76 additions & 21 deletions test/RougeFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ var RGEToken = artifacts.require("./TestRGEToken.sol");
var Factory = artifacts.require("./RougeFactory.sol");
var SimpleRougeCampaign = artifacts.require("./SimpleRougeCampaign.sol");

var tare = 0.1 * 10**6; /* price price is 0.1 rge in beta phase */

contract('RougeFactory', function(accounts) {

it("create a simple Rouge campaign", async function() {

var user = accounts[1];
var issuer = accounts[1];
var tokens = 1000 * 10**6; /* 1K RGE tokens */

var issuance = 10;
Expand All @@ -16,23 +18,23 @@ contract('RougeFactory', function(accounts) {
let rge = await RGEToken.deployed();
let factory = await Factory.deployed();

let user_balance_before = await rge.balanceOf.call(user);
assert.equal(user_balance_before.toNumber(), 0, "user has no rge tokens to start with");
let issuer_balance_before = await rge.balanceOf.call(issuer);
assert.equal(issuer_balance_before.toNumber(), 0, "issuer has no rge tokens to start with");

await rge.giveMeRGE(tokens, {from: user});
await rge.giveMeRGE(tokens, {from: issuer});

let user_balance_post = await rge.balanceOf.call(user);
assert.equal(user_balance_post.toNumber(), tokens, "user has receive tokens to create a campaign");
let issuer_balance_post = await rge.balanceOf.call(issuer);
assert.equal(issuer_balance_post.toNumber(), tokens, "issuer has receive tokens to create a campaign");

await rge.newCampaign(issuance, deposit, {from: user, gas: 2000000, gasPrice: web3.toWei(1, "gwei")})
await rge.newCampaign(issuance, deposit, {from: issuer, gas: 2000000, gasPrice: web3.toWei(1, "gwei")})

let user_balance_after = await rge.balanceOf.call(user);
assert.equal(user_balance_after.toNumber(), tokens - deposit, "user has sent tokens as a deposit to the factory");
let issuer_balance_after = await rge.balanceOf.call(issuer);
assert.equal(issuer_balance_after.toNumber(), tokens - deposit, "issuer has sent tokens as a deposit to the factory");

let campaign_count = await factory.get_all_count.call();
assert.equal(campaign_count.toNumber(), 1, "one campaign has been created");

let campaign_address = await factory.get_campaign.call(user, 0);
let campaign_address = await factory.get_campaign.call(issuer, 0);

let factory_balance = await rge.balanceOf.call(factory.address);
assert.equal(factory_balance.toNumber(), 0, "no tokens deposit in the factory");
Expand All @@ -42,11 +44,9 @@ contract('RougeFactory', function(accounts) {

});

it("simple tare burning test", async function() {

var tare = 0.1 * 10**6; /* price price is 0.1 rge in beta phase */
it("simple tare burning test with no redemption", async function() {

var user = accounts[2];
var issuer = accounts[2];
var tokens = 1000 * 10**6;

var issuance = 10;
Expand All @@ -55,9 +55,9 @@ contract('RougeFactory', function(accounts) {
let rge = await RGEToken.deployed();
let factory = await Factory.deployed();

await rge.giveMeRGE(tokens, {from: user});
await rge.newCampaign(issuance, deposit, {from: user, gas: 2000000, gasPrice: web3.toWei(1, "gwei")})
let campaign_address = await factory.get_campaign.call(user, 0);
await rge.giveMeRGE(tokens, {from: issuer});
await rge.newCampaign(issuance, deposit, {from: issuer, gas: 2000000, gasPrice: web3.toWei(1, "gwei")})
let campaign_address = await factory.get_campaign.call(issuer, 0);

let ftare = await factory.tare.call();
assert.equal(ftare.toNumber(), tare, "tare price is set correctly in factory");
Expand All @@ -68,20 +68,75 @@ contract('RougeFactory', function(accounts) {
let campaign = SimpleRougeCampaign.at(campaign_address);

// very long expiration // 19 January, 2038 03:14:07 UT ( 2147483647 )
await campaign.issue('Test Simple 2', 2147483647, {from: user});
await campaign.issue('Test Simple 2', 2147483647, {from: issuer});

let available = await campaign.available.call();
assert.equal(available.toNumber(), issuance, "check notes available after issuance");

await campaign.kill({from: user});
await campaign.kill({from: issuer});

let burned = tare * issuance;

let campaign_balance_after = await rge.balanceOf.call(campaign_address);
assert.equal(campaign_balance_after.toNumber(), 0, "the campaign has no more rge after kill");

let user_balance_after = await rge.balanceOf.call(user);
assert.equal(user_balance_after.toNumber(), tokens - burned, "the user has his tokens back less tare for 10 notes");
let issuer_balance_after = await rge.balanceOf.call(issuer);
assert.equal(issuer_balance_after.toNumber(), tokens - burned, "the issuer has his tokens back less tare for 10 notes");

});

it("acceptRedemption from issuer", async function() {

var issuer = accounts[3];
var bearer = accounts[4];

var tokens = 1000 * 10**6;
var issuance = 10;
var deposit = 50 * 10**6;

let rge = await RGEToken.deployed();
let factory = await Factory.deployed();

await rge.giveMeRGE(tokens, {from: issuer});
await rge.newCampaign(issuance, deposit, {from: issuer, gas: 2000000, gasPrice: web3.toWei(1, "gwei")})
let campaign_address = await factory.get_campaign.call(issuer, 0);

let campaign_balance = await rge.balanceOf.call(campaign_address);
assert.equal(campaign_balance.toNumber(), deposit, "the tokens deposit is now in the new campaign contract");

let campaign = SimpleRougeCampaign.at(campaign_address);

await campaign.issue('acceptRedemption Test', 2147483647, {from: issuer});
await campaign.giveNote(bearer, {from: issuer});

let acquired = await campaign.acquired.call();
assert.equal(acquired.toNumber(), 1, "check notes acquired after giveNote");

// at minimum, msg needs to include the campaign address to protect against replay
let msg = campaign_address + 'valid ticket';

// bearer signature that to be used by issuer
let signature = web3.eth.sign(bearer, web3.sha3(msg));
signature = signature.substr(2);
const r = '0x' + signature.slice(0, 64)
const s = '0x' + signature.slice(64, 128)
const v = '0x' + signature.slice(128, 130)
const v_decimal = web3.toDecimal(v) + 27

await campaign.acceptRedemption(bearer, web3.sha3(msg), v_decimal, r, s, {from: issuer});

let redeemed = await campaign.redeemed.call();
assert.equal(redeemed.toNumber(), 1, "notes redeemed after confirmRedemption");

await campaign.kill({from: issuer});

let burned = tare * (issuance - 1);

let campaign_balance_after = await rge.balanceOf.call(campaign_address);
assert.equal(campaign_balance_after.toNumber(), 0, "the campaign has no more rge after kill");

let issuer_balance_after = await rge.balanceOf.call(issuer);
assert.equal(issuer_balance_after.toNumber(), tokens - burned, "the issuer has his tokens back less tare for unredeemed notes");

});

Expand Down

0 comments on commit 27b4b87

Please sign in to comment.