├── .eslintrc
├── .gitignore
├── .gitmodules
├── .solcover.js
├── .soliumignore
├── .soliumrc.json
├── .travis.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── SOLIDITY_STYLE_GUIDE.md
├── VERSION
├── contracts
├── BrandedToken.sol
├── EIP20Interface.sol
├── EIP20Token.sol
├── EIP20TokenMock.sol
├── GatewayComposer.sol
├── GatewayInterface.sol
├── UtilityBrandedToken.sol
├── test
│ ├── MockCoGateway.sol
│ ├── TestUtilityBrandedToken.sol
│ ├── branded_token
│ │ └── MockBrandedTokenFail.sol
│ ├── eip20token
│ │ ├── EIP20TokenMockFail.sol
│ │ ├── EIP20TokenMockPass.sol
│ │ └── EIP20TokenMockPassFail.sol
│ ├── gateway
│ │ ├── MockGatewayFail.sol
│ │ └── MockGatewayPass.sol
│ └── organization
│ │ ├── OrganizationMockFail.sol
│ │ ├── OrganizationMockPass.sol
│ │ └── OrganizationMockWorker.sol
└── truffle
│ └── Migrations.sol
├── dist
└── index.js
├── migrations
└── 1_initial_migration.js
├── package-lock.json
├── package.json
├── test
├── branded_token
│ ├── accept_stake_request.js
│ ├── constructor.js
│ ├── convert_to_branded_tokens.js
│ ├── convert_to_value_tokens.js
│ ├── lift_all_restrictions.js
│ ├── lift_restriction.js
│ ├── redeem.js
│ ├── reject_stake_request.js
│ ├── request_stake.js
│ ├── revoke_stake_request.js
│ ├── set_name.js
│ ├── set_symbol.js
│ ├── transfer.js
│ ├── transferFrom.js
│ └── utils.js
├── gateway_composer
│ ├── accept_stake_request.js
│ ├── approve_token.js
│ ├── constructor.js
│ ├── destroy.js
│ ├── request_stake.js
│ ├── revert_stake.js
│ ├── revoke_stake_request.js
│ ├── transfer_token.js
│ └── utils.js
├── test_lib
│ ├── RevertProxy.sol
│ ├── config.js
│ ├── event_decoder.js
│ ├── utils.js
│ └── web3.js
└── utility_branded_token
│ ├── constructor.js
│ ├── decrease_supply.js
│ ├── exists.js
│ ├── increase_supply.js
│ ├── register_internal_actors.js
│ ├── set_cogateway.js
│ ├── transfer.js
│ ├── transfer_from.js
│ └── utils.js
├── tools
├── build_package.js
├── compile.sh
├── runGanacheCli.sh
└── test_range.sh
└── truffle.js
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "airbnb-base"
4 | ],
5 | "rules": {
6 | "no-console": "off",
7 | "no-underscore-dangle": "off",
8 | "import/no-extraneous-dependencies": "off",
9 | "strict": "off"
10 | },
11 | "env": {
12 | "mocha": true,
13 | "node": true,
14 | "es6": true
15 | },
16 | "globals": {
17 | "artifacts": false,
18 | "contract": false,
19 | "assert": false
20 | }
21 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | .DS_Store
3 | .idea/
4 |
5 | # VS Code
6 | .vscode
7 |
8 | # Vagrant
9 | .vagrant/
10 | ubuntu-xenial-16.04-cloudimg-console.log
11 |
12 | # don't commit node_modules
13 | node_modules
14 |
15 | build/
16 |
17 | contracts/abi/
18 | contracts/bin/
19 |
20 | # NPM package generated files:
21 | dist/contracts.json
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "contracts/utilitytoken"]
2 | path = contracts/utilitytoken
3 | url = https://github.com/OpenST/utilitytoken-contracts.git
4 |
--------------------------------------------------------------------------------
/.solcover.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | port: 8555,
3 | compileCommand: '../node_modules/.bin/truffle compile',
4 | testCommand: '../node_modules/.bin/truffle test --network coverage',
5 | skipFiles: ['truffle/Migrations.sol']
6 | };
--------------------------------------------------------------------------------
/.soliumignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | contracts/Migrations.sol
3 | contracts/SafeMath.sol
4 |
--------------------------------------------------------------------------------
/.soliumrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "solium:recommended",
3 | "plugins": [
4 | "security"
5 | ],
6 | "rules": {
7 | "imports-on-top": 0,
8 | "variable-declarations": 0,
9 | "quotes": [
10 | "error",
11 | "double"
12 | ],
13 | "indentation": [
14 | "error",
15 | 4
16 | ],
17 | "max-len": [
18 | "error",
19 | 79
20 | ]
21 | }
22 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: trusty
2 | language: node_js
3 | sudo: required
4 | branches:
5 | only:
6 | - master
7 | - develop
8 | - /^release-.*/
9 | notifications:
10 | email:
11 | recipients:
12 | - ci.report@ost.com
13 | on_success: always
14 | on_failure: always
15 | node_js:
16 | - "8"
17 | before_install:
18 | - sudo apt-get update
19 | - sudo apt-get install nodejs
20 | - sudo apt-get install npm
21 | install:
22 | - npm install
23 | before_script:
24 | - nohup sh tools/runGanacheCli.sh /dev/null 2>&1 &
25 | script:
26 | - npm run lint
27 | - npm run test
28 | - npm run compile-all
29 | - npm run build-package
30 | after_script:
31 | - kill $(ps aux | grep 'testrpc' | awk '{print $2}')
32 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Branded Token Contracts Change Log
2 |
3 | Below is a list of notable changes implemented in this repository.
4 |
5 | ## 0.10.0
6 |
7 |
8 | * Contracts: Implementation of exists in UtilityBrandedToken contract. ([#153](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/153))
9 | * Contracts: Register cogateway as an internal actor on UtilityBrandedToken::setCoGateway(). ([#151](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/151))
10 | * Contracts: Remove reentrancy from BrandedToken::acceptStakeRequest() ([#150](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/150))
11 | * Contracts: GatewayComposer: Reentrancy evaluation and prevention mechanisms ([#147](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/147))
12 | * Contracts: update and test SafeMath ([#127](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/127))
13 | * Tests: Fix negative tests with unresolved promises ([#118](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/118))
14 | * Tests: Complete testing of various BrandedToken functions ([#114](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/114))
15 | * Tests: Add negative test for BrandedToken's liftAllRestrictions ([#111](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/111))
16 | * Tests: Add negative test for BrandedToken's redeem ([#108](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/108))
17 | * Contracts: Limit BrandedToken conversionRateDecimals to 5 ([#107](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/107))
18 | * Contracts: Calculate stakeRequestHash per EIP 712 ([#105](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/105))
19 | * Contracts: Add destroy to GatewayComposer ([#103](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/103))
20 | * Contracts: Add setName and setSymbol for BrandedToken ([#102](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/102))
21 | * Contracts: Initially implement GatewayComposer ([#88](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/88))
22 | * Contracts: Add initial implementation of BrandedToken ([#87](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/87))
23 | * Contracts: Update contracts for Solidity 0.5.0 ([#76](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/76))
24 | * Tests: Test Internal ([#51](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/51))
25 | * Contracts: Implement UtilityBrandedToken ([#47](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/47))
26 | * Contracts: Add Internal for use with UtilityBrandedToken ([#43](https://github.com/OpenSTFoundation/brandedtoken-contracts/pull/43))
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@ost.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Branded Tokens - Tokenizing Mainstream Applications
2 |
3 | [](https://discuss.openst.org/) [](https://travis-ci.org/OpenST/brandedtoken-contracts)
4 |
5 | A Branded Token allows a mainstream application to create a value-backed token designed specifically for its application's context. A Branded Token implements the required and optional [EIP-20 Standard Token interface](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md).
6 |
7 | Holders of branded tokens must be able to redeem the value that backs those branded tokens. Branded tokens are only usable within the application context. The application can maintain a policy on accepting new holders.
8 |
9 | A Utility Branded Token, which also implements the EIP-20 Standard Token interface, is the utility token representation of the Branded Token on a sidechain. This representation is orchestrated via a gateway, comprising a Gateway contract on the same chain as the Branded Token, and a CoGateway contract on the sidechain with the Utility Branded Token.
10 |
11 | A composer is a contract that can be used to optimize the transactions required to perform an action. A Gateway Composer, a type of composer, facilitate's staking value for branded tokens and minting a utility representation of those branded tokens with a Utility Branded Token through a gateway for use within the given application, thereby reducing both the number of transactions to execute and the number of contracts to call in order to stake and mint.
12 |
13 | The complete Branded Token specification is in a draft proposal and subject to change. For more information on the specification, please consult [OIP-0001](https://github.com/OpenST/OIPs/blob/master/OIPS/oip-0001.md) in the OpenST Improvement Proposals repository.
14 |
15 | ## Related Projects
16 |
17 | Significant related projects are:
18 |
19 | - [brandedtoken.js](https://github.com/OpenST/brandedtoken.js): a library for interacting with `BrandedToken` and `GatewayComposer` contracts.
20 | - [mosaic-contracts](https://github.com/OpenST/mosaic-contracts): a set of meta-blockchains on top of Ethereum to scale (D)Apps
21 | - [mosaic.js](https://github.com/OpenST/mosaic.js): a web3 interface to scale (D)Apps on Ethereum
22 | - [openst-contracts](https://github.com/OpenST/openst-contracts): a framework for building token economies
23 | - [openst.js](https://github.com/OpenST/openst.js): a library for deploying and interacting with a token economy
24 |
25 | ## Contributing
26 |
27 | There are multiple ways to contribute to this project. However, before contributing, please first review the [Code of Conduct](CODE_OF_CONDUCT.md).
28 |
29 | To participate in the discussion on technical matters, please join the project's [Discourse forum](https://discuss.openst.org/) channel or review the project's [issues](https://github.com/OpenSTFoundation/brandedtoken-contracts/issues).
30 |
31 | To contribute code, please ensure that your submissions adhere to the [Style Guide](SOLIDITY_STYLE_GUIDE.md); please also be aware, this project is under active development and we have not yet established firm contribution guidelines or acceptance criteria.
32 |
33 | ## OpenST
34 |
35 | OpenST blockchain infrastructure empowers new economies for mainstream businesses and emerging (D)Apps. The smart contracts in this repository are intended for use with the OpenST Protocol, a framework for tokenizing businesses.
36 |
37 | For more information on the OpenST Protocol, please consult the [Whitepaper](https://drive.google.com/file/d/0Bwgf8QuAEOb7Z2xIeUlLd21DSjQ/view).
38 |
39 | _While this software is available as-is for anyone to use, we caution that this is in early stage and under heavy ongoing development and improvement. Please report bugs and suggested improvements._
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 0.10.0
--------------------------------------------------------------------------------
/contracts/EIP20Interface.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 | //
17 | // ----------------------------------------------------------------------------
18 | // Common: Standard EIP20 Interface
19 | //
20 | // http://www.simpletoken.org/
21 | //
22 | // ----------------------------------------------------------------------------
23 | // ----------------------------------------------------------------------------
24 | // Based on the 'final' EIP20 token standard as specified at:
25 | // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
26 | // ----------------------------------------------------------------------------
27 |
28 | /**
29 | * @title EIP20Interface.
30 | *
31 | * @notice Provides EIP20 token interface.
32 | */
33 | contract EIP20Interface {
34 |
35 | /* Events */
36 |
37 | event Transfer(
38 | address indexed _from,
39 | address indexed _to,
40 | uint256 _value
41 | );
42 |
43 | event Approval(
44 | address indexed _owner,
45 | address indexed _spender,
46 | uint256 _value
47 | );
48 |
49 |
50 | /* Public functions */
51 |
52 | /**
53 | * @notice Public function to get the name of the token.
54 | *
55 | * @return tokenName_ Name of the token.
56 | */
57 | function name() public view returns (string memory tokenName_);
58 |
59 | /**
60 | * @notice Public function to get the symbol of the token.
61 | *
62 | * @return tokenSymbol_ Symbol of the token.
63 | */
64 | function symbol() public view returns (string memory tokenSymbol_);
65 |
66 | /**
67 | * @notice Public function to get the decimals of the token.
68 | *
69 | * @return tokenDecimals Decimals of the token.
70 | */
71 | function decimals() public view returns (uint8 tokenDecimals_);
72 |
73 | /**
74 | * @notice Public function to get the total supply of the tokens.
75 | *
76 | * @return totalTokenSupply_ Total token supply.
77 | */
78 | function totalSupply()
79 | public
80 | view
81 | returns (uint256 totalTokenSupply_);
82 |
83 | /**
84 | * @notice Get the balance of an account.
85 | *
86 | * @param _owner Address of the owner account.
87 | *
88 | * @return balance_ Account balance of the owner account.
89 | */
90 | function balanceOf(address _owner) public view returns (uint256 balance_);
91 |
92 | /**
93 | * @notice Public function to get the allowance.
94 | *
95 | * @param _owner Address of the owner account.
96 | * @param _spender Address of the spender account.
97 | *
98 | * @return allowance_ Remaining allowance for the spender to spend from
99 | * owner's account.
100 | */
101 | function allowance(
102 | address _owner,
103 | address _spender
104 | )
105 | public
106 | view
107 | returns (uint256 allowance_);
108 |
109 |
110 | /**
111 | * @notice Public function to transfer the token.
112 | *
113 | * @param _to Address to which tokens are transferred.
114 | * @param _value Amount of tokens to be transferred.
115 | *
116 | * @return success_ `true` for a successful transfer, `false` otherwise.
117 | */
118 | function transfer(
119 | address _to,
120 | uint256 _value
121 | )
122 | public
123 | returns (bool success_);
124 |
125 | /**
126 | * @notice Public function transferFrom.
127 | *
128 | * @param _from Address from which tokens are transferred.
129 | * @param _to Address to which tokens are transferred.
130 | * @param _value Amount of tokens transferred.
131 | *
132 | * @return success_ `true` for a successful transfer, `false` otherwise.
133 | */
134 | function transferFrom(
135 | address _from,
136 | address _to,
137 | uint256 _value
138 | )
139 | public
140 | returns (bool success_);
141 |
142 | /**
143 | * @notice Public function to approve an account for transfer.
144 | *
145 | * @param _spender Address authorized to spend from the function caller's
146 | * address.
147 | * @param _value Amount up to which spender is authorized to spend.
148 | *
149 | * @return bool `true` for a successful approval, `false` otherwise.
150 | */
151 | function approve(
152 | address _spender,
153 | uint256 _value
154 | )
155 | public
156 | returns (bool success_);
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/contracts/EIP20Token.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | import "./EIP20Interface.sol";
18 | import "openzeppelin-solidity/contracts/math/SafeMath.sol";
19 |
20 |
21 | /**
22 | * @title EIP20Token contract which implements EIP20Interface.
23 | *
24 | * @notice Implements EIP20 token.
25 | */
26 | contract EIP20Token is EIP20Interface {
27 |
28 | using SafeMath for uint256;
29 |
30 |
31 | /* Storage */
32 |
33 | string internal tokenName;
34 | string internal tokenSymbol;
35 | uint8 private tokenDecimals;
36 | uint256 internal totalTokenSupply;
37 |
38 | mapping(address => uint256) balances;
39 | mapping(address => mapping (address => uint256)) allowed;
40 |
41 |
42 | /* Special functions */
43 |
44 | /**
45 | * @notice Contract constructor.
46 | *
47 | * @param _symbol Symbol of the token.
48 | * @param _name Name of the token.
49 | * @param _decimals Decimal places of the token.
50 | */
51 | constructor(
52 | string memory _symbol,
53 | string memory _name,
54 | uint8 _decimals
55 | )
56 | public
57 | {
58 | tokenSymbol = _symbol;
59 | tokenName = _name;
60 | tokenDecimals = _decimals;
61 | totalTokenSupply = 0;
62 | }
63 |
64 |
65 | /* Public functions */
66 |
67 | /**
68 | * @notice Public view function name.
69 | *
70 | * @return Name of the token.
71 | */
72 | function name() public view returns (string memory) {
73 | return tokenName;
74 | }
75 |
76 | /**
77 | * @notice Public view function symbol.
78 | *
79 | * @return Symbol of the token.
80 | */
81 | function symbol() public view returns (string memory) {
82 | return tokenSymbol;
83 | }
84 |
85 | /**
86 | * @notice Public view function decimals.
87 | *
88 | * @return Decimal places of the token.
89 | */
90 | function decimals() public view returns (uint8) {
91 | return tokenDecimals;
92 | }
93 |
94 | /**
95 | * @notice Public view function balanceOf.
96 | *
97 | * @param _owner Address of the owner account.
98 | *
99 | * @return Account balance of the owner account.
100 | */
101 | function balanceOf(address _owner) public view returns (uint256) {
102 | return balances[_owner];
103 | }
104 |
105 | /**
106 | * @notice Public view function totalSupply.
107 | *
108 | * @dev Get totalTokenSupply as view so that child cannot edit.
109 | *
110 | * @return Total token supply.
111 | */
112 | function totalSupply()
113 | public
114 | view
115 | returns (uint256)
116 | {
117 | return totalTokenSupply;
118 | }
119 |
120 | /**
121 | * @notice Public view function allowance.
122 | *
123 | * @param _owner Address of the owner account.
124 | * @param _spender Address of the spender account.
125 | *
126 | * @return Remaining allowance for the spender to spend from
127 | * owner's account.
128 | */
129 | function allowance(
130 | address _owner,
131 | address _spender
132 | )
133 | public
134 | view
135 | returns (uint256)
136 | {
137 | return allowed[_owner][_spender];
138 | }
139 |
140 | /**
141 | * @notice Public function transfer.
142 | *
143 | * @dev Fires the transfer event, throws if, _from account does not have
144 | * enough tokens to spend.
145 | *
146 | * @param _to Address to which tokens are transferred.
147 | * @param _value Amount of tokens to be transferred.
148 | *
149 | * @return success_ True for a successful transfer, false otherwise.
150 | */
151 | function transfer(
152 | address _to,
153 | uint256 _value
154 | )
155 | public
156 | returns (bool success_)
157 | {
158 |
159 | // According to the EIP20 spec, "transfers of 0 values MUST be treated
160 | // as normal transfers and fire the Transfer event".
161 | // Also, should throw if not enough balance. This is taken care of by
162 | // SafeMath.
163 | balances[msg.sender] = balances[msg.sender].sub(_value);
164 | balances[_to] = balances[_to].add(_value);
165 |
166 | emit Transfer(msg.sender, _to, _value);
167 |
168 | return true;
169 | }
170 |
171 | /**
172 | * @notice Public function transferFrom.
173 | *
174 | * @dev Allows a contract to transfer tokens on behalf of _from address
175 | * to _to address, the function caller has to be pre-authorized
176 | * for multiple transfers up to the total of _value amount by
177 | * the _from address.
178 | *
179 | * @param _from Address from which tokens are transferred.
180 | * @param _to Address to which tokens are transferred.
181 | * @param _value Amount of tokens transferred.
182 | *
183 | * @return success_ True for a successful transfer, false otherwise.
184 | */
185 | function transferFrom(
186 | address _from,
187 | address _to,
188 | uint256 _value
189 | )
190 | public
191 | returns (bool success_)
192 | {
193 | balances[_from] = balances[_from].sub(_value);
194 | allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
195 | balances[_to] = balances[_to].add(_value);
196 |
197 | emit Transfer(_from, _to, _value);
198 |
199 | return true;
200 | }
201 |
202 | /**
203 | * @notice Public function approve.
204 | *
205 | * @dev Allows _spender address to withdraw from function caller's
206 | * account, multiple times up to the _value amount, if this
207 | * function is called again it overwrites the current allowance
208 | * with _value.
209 | *
210 | * @param _spender Address authorized to spend from the function caller's
211 | * address.
212 | * @param _value Amount up to which spender is authorized to spend.
213 | *
214 | * @return success_ True for a successful approval, false otherwise.
215 | */
216 | function approve(
217 | address _spender,
218 | uint256 _value
219 | )
220 | public
221 | returns (bool success_)
222 | {
223 |
224 | allowed[msg.sender][_spender] = _value;
225 |
226 | emit Approval(msg.sender, _spender, _value);
227 |
228 | return true;
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/contracts/EIP20TokenMock.sol:
--------------------------------------------------------------------------------
1 | /* solhint-disable-next-line compiler-fixed */
2 | pragma solidity ^0.5.0;
3 |
4 | // Copyright 2018 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | import "./EIP20Token.sol";
19 |
20 |
21 | /**
22 | * @title EIP20TokenMock contract.
23 | *
24 | * @notice It provides EIP20Token with mock functionality to facilitate
25 | * testing.
26 | */
27 | contract EIP20TokenMock is EIP20Token {
28 |
29 | /* Special functions */
30 |
31 | /**
32 | * @dev Takes _symbol, _name, _decimals.
33 | *
34 | * @param _symbol Symbol.
35 | * @param _name Name.
36 | * @param _decimals Decimals.
37 | */
38 | constructor(
39 | string memory _symbol,
40 | string memory _name,
41 | uint8 _decimals
42 | )
43 | /* solhint-disable-next-line visibility-modifier-order */
44 | EIP20Token(_symbol, _name, _decimals)
45 | public
46 | { }
47 |
48 |
49 | /* Public functions */
50 |
51 | /**
52 | * @notice Returns 0 as mock total supply.
53 | *
54 | * @return Returns 0.
55 | */
56 | function totalSupply()
57 | public
58 | view
59 | returns (uint256)
60 | {
61 | return 0;
62 | }
63 |
64 | /**
65 | * @notice Takes _owner, _value; sets balance of _owner to _value.
66 | *
67 | * @param _owner Owner.
68 | * @param _value Value.
69 | *
70 | * @return True if balances of the _owner is set.
71 | */
72 | function setBalance(
73 | address _owner,
74 | uint256 _value
75 | )
76 | public
77 | returns (bool)
78 | {
79 | balances[_owner] = _value;
80 | return true;
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/contracts/GatewayInterface.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 |
18 | /**
19 | * @title GatewayInterface Contract
20 | *
21 | * @notice Provides interface for gateway contract.
22 | */
23 | interface GatewayInterface {
24 |
25 | /* External functions */
26 |
27 | /**
28 | * @notice Returns bounty amount.
29 | *
30 | * @return Amount of ERC20 which needs to be staked by facilitator.
31 | */
32 | function bounty()
33 | external
34 | returns (uint256);
35 |
36 | /**
37 | * @notice Initiates the stake process. In order to stake the staker
38 | * needs to approve Gateway contract for stake amount.
39 | * Staked amount is transferred from staker address to
40 | * Gateway contract. Bounty amount is also transferred from staker.
41 | *
42 | * @param _amount Stake amount that will be transferred from the staker
43 | * account.
44 | * @param _beneficiary The address in the auxiliary chain where the utility
45 | * tokens will be minted.
46 | * @param _gasPrice Gas price that staker is ready to pay to get the stake
47 | * and mint process done.
48 | * @param _gasLimit Gas limit that staker is ready to pay.
49 | * @param _nonce Nonce of the staker address.
50 | * @param _hashLock Hash Lock provided by the facilitator.
51 | *
52 | * @return messageHash_ Message hash is unique for each request.
53 | */
54 | function stake(
55 | uint256 _amount,
56 | address _beneficiary,
57 | uint256 _gasPrice,
58 | uint256 _gasLimit,
59 | uint256 _nonce,
60 | bytes32 _hashLock
61 | )
62 | external
63 | returns (bytes32 messageHash_);
64 |
65 | /**
66 | * @notice Revert stake process and get the stake
67 | * amount back. Only staker can revert stake by providing
68 | * penalty i.e. 1.5 times of bounty amount. On progress revert stake
69 | * penalty and facilitator bounty will be burned.
70 | *
71 | * @dev To revert the the sender must sign the sha3(messageHash, nonce+1)
72 | *
73 | * @param _messageHash Message hash.
74 | *
75 | * @return staker_ Staker address
76 | * @return stakerNonce_ Staker nonce
77 | * @return amount_ Stake amount
78 | */
79 | function revertStake(
80 | bytes32 _messageHash
81 | )
82 | external
83 | returns
84 | (
85 | address staker_,
86 | uint256 stakerNonce_,
87 | uint256 amount_
88 | );
89 | }
90 |
--------------------------------------------------------------------------------
/contracts/UtilityBrandedToken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | import "./utilitytoken/contracts/UtilityToken.sol";
18 |
19 |
20 | /**
21 | * @title UtilityBrandedToken contract.
22 | *
23 | * @notice UtilityBrandedToken is an EIP20 token which implements
24 | * UtilityTokenInterface.
25 | *
26 | * @dev UtilityBrandedToken are designed to be used within a decentralised
27 | * application and support increaseSupply and decreaseSupply of tokens.
28 | */
29 | contract UtilityBrandedToken is UtilityToken {
30 |
31 | /* Events */
32 |
33 | event InternalActorRegistered(
34 | address _actor
35 | );
36 |
37 |
38 | /* Storage */
39 |
40 | /** Mapping stores addresses which are registered as internal actor. */
41 | mapping (address /* internal actor */ => bool) public isInternalActor;
42 |
43 |
44 | /* Special Functions */
45 |
46 | /**
47 | * @notice Contract constructor.
48 | *
49 | * @dev Creates an utility branded token contract with arguments passed
50 | * in the contract constructor.
51 | *
52 | * @param _token Address of branded token on origin chain.
53 | * It acts as an identifier.
54 | * @param _symbol Symbol of the token.
55 | * @param _name Name of the token.
56 | * @param _decimals Decimal places of the token.
57 | * @param _organization Address of the Organization contract.
58 | */
59 | constructor(
60 | address _token,
61 | string memory _symbol,
62 | string memory _name,
63 | uint8 _decimals,
64 | OrganizationInterface _organization
65 | )
66 | public
67 | UtilityToken(_token, _symbol, _name, _decimals, _organization)
68 | {
69 | }
70 |
71 |
72 | /* External functions */
73 |
74 | /**
75 | * @notice Registers internal actors.
76 | *
77 | * @param _internalActors Array of addresses of the internal actors
78 | * to register.
79 | */
80 | function registerInternalActors(address[] calldata _internalActors)
81 | external
82 | onlyWorker
83 | {
84 | for (uint256 i = 0; i < _internalActors.length; i++) {
85 | if (!isInternalActor[_internalActors[i]]) {
86 | isInternalActor[_internalActors[i]] = true;
87 | emit InternalActorRegistered(_internalActors[i]);
88 | }
89 | }
90 | }
91 |
92 | /**
93 | * @notice Sets the CoGateway contract address.
94 | *
95 | * @dev Function requires:
96 | * - Caller is organization.
97 | * - coGateway address is not set.
98 | * - coGateway.utilityToken is equal to this contract address.
99 | *
100 | * @param _coGateway CoGateway contract address.
101 | */
102 | function setCoGateway(address _coGateway)
103 | external
104 | onlyOrganization
105 | returns (bool success_)
106 | {
107 | success_ = super.setCoGatewayInternal(_coGateway);
108 |
109 | // Registers co-gateway as an internal actor.
110 | isInternalActor[coGateway] = true;
111 | }
112 |
113 | /**
114 | * @notice Increases the total token supply. Also, adds the number of
115 | * tokens to the beneficiary balance.
116 | *
117 | * @param _beneficiary Account address for which the balance will be
118 | * increased. This is payable so that it provides
119 | * flexibility of transferring base token to account
120 | * on increase supply.
121 | * @param _amount Amount of tokens.
122 | *
123 | * @return success_ `true` if increase supply is successful, false otherwise.
124 | */
125 | function increaseSupply(
126 | address payable _beneficiary,
127 | uint256 _amount
128 | )
129 | external
130 | onlyCoGateway
131 | returns (bool success_)
132 | {
133 | require(
134 | isInternalActor[_beneficiary],
135 | "Beneficiary is not an internal actor."
136 | );
137 |
138 | success_ = super.increaseSupplyInternal(_beneficiary, _amount);
139 | }
140 |
141 | /**
142 | * @notice Checks if an address is an internal actor.
143 | *
144 | * @return exists_ `true` if the specified account is an internal actor,
145 | * otherwise `false`.
146 | */
147 | function exists(address account) external returns (bool exists_) {
148 | exists_ = isInternalActor[account];
149 | }
150 |
151 |
152 | /* Public functions */
153 |
154 | /**
155 | * @notice Public function transfer.
156 | *
157 | * @dev Function requires:
158 | * - _to address is an internal actor
159 | *
160 | * @param _to Address to which BT needs to transfer.
161 | * @param _value Number of BTs that needs to transfer.
162 | *
163 | * @return Success/failure status of transfer.
164 | */
165 | function transfer(
166 | address _to,
167 | uint256 _value
168 | )
169 | public
170 | returns (bool)
171 | {
172 | require(
173 | isInternalActor[_to],
174 | "To address is not an internal actor."
175 | );
176 |
177 | return super.transfer(_to, _value);
178 | }
179 |
180 | /**
181 | * @notice Public function transferFrom.
182 | *
183 | * @dev Function requires:
184 | * - _to address is an internal actor
185 | *
186 | * @param _from Address from which BT needs to transfer.
187 | * @param _to Address to which BT needs to transfer.
188 | * @param _value Number of BTs that needs to transfer.
189 | *
190 | * @return Success/failure status of transferFrom.
191 | */
192 | function transferFrom(
193 | address _from,
194 | address _to,
195 | uint256 _value
196 | )
197 | public
198 | returns (bool)
199 | {
200 | require(
201 | isInternalActor[_to],
202 | "To address is not an internal actor."
203 | );
204 |
205 | return super.transferFrom(_from, _to, _value);
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/contracts/test/MockCoGateway.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 |
18 | /**
19 | * @title MockCoGateway contract.
20 | *
21 | * @notice It contains utility token address.
22 | */
23 | contract MockCoGateway {
24 |
25 |
26 | /* Storage */
27 |
28 | /** Address of utilityToken */
29 | address private token;
30 |
31 |
32 | /* Special functions */
33 |
34 | constructor(address _token) public {
35 |
36 | token = _token;
37 |
38 | }
39 |
40 |
41 | /* Public methods */
42 |
43 | /**
44 | * @notice Get the utility token address.
45 | *
46 | * @return Address of utility token.
47 | */
48 | function utilityToken() public view returns (address)
49 | {
50 | return token;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/contracts/test/TestUtilityBrandedToken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | import "../UtilityBrandedToken.sol";
18 | import "../utilitytoken/contracts/organization/contracts/OrganizationInterface.sol";
19 |
20 |
21 | /**
22 | * @title TestUtilityBrandedToken contract.
23 | *
24 | * @notice UtilityBrandedToken is inheriting UtilityBrandedToken contract.
25 | *
26 | * @dev TestUtilityBrandedToken facilitates testing of UtilityBrandedToken.
27 | *
28 | */
29 | contract TestUtilityBrandedToken is UtilityBrandedToken {
30 |
31 | /* Special Function */
32 |
33 | /**
34 | * @notice Contract constructor.
35 | *
36 | * @dev Creates an EIP20Token contract with arguments passed in the
37 | * contract constructor.
38 | *
39 | * @param _token Address of branded token on origin chain.
40 | * It acts as an identifier.
41 | * @param _symbol Symbol of the token.
42 | * @param _name Name of the token.
43 | * @param _decimals Decimal places of the token.
44 | * @param _organization Address of the Organization contract.
45 | */
46 | constructor(
47 | address _token,
48 | string memory _symbol,
49 | string memory _name,
50 | uint8 _decimals,
51 | OrganizationInterface _organization
52 | )
53 | public
54 | UtilityBrandedToken(_token, _symbol, _name, _decimals, _organization)
55 | {}
56 |
57 |
58 | /* Public functions */
59 |
60 | /**
61 | * @dev Takes _owner, _value; sets balance of _owner to _value.
62 | *
63 | * @notice It sets the balance for an address.
64 | *
65 | * @param _owner Owner address.
66 | * @param _value Amount of BT's to be set.
67 | *
68 | * @return True if success.
69 | */
70 | function setBalance(
71 | address _owner,
72 | uint256 _value
73 | )
74 | public
75 | returns (bool)
76 | {
77 | balances[_owner] = _value;
78 | return true;
79 | }
80 |
81 | /**
82 | * @dev It is used in testing increaseSupply and decreaseSupply methods.
83 | *
84 | * @notice It sets the coGateway address.
85 | *
86 | * @param _coGatewayAddress CoGateway contract address.
87 | */
88 | function mockSetCoGateway(address _coGatewayAddress) public {
89 | coGateway = _coGatewayAddress;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/contracts/test/branded_token/MockBrandedTokenFail.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | import "./../../BrandedToken.sol";
18 |
19 |
20 | /**
21 | * @title MockBrandedTokenFail.
22 | *
23 | * @notice Supports testing of BrandedToken(BT) failure cases.
24 | */
25 | contract MockBrandedTokenFail is BrandedToken {
26 |
27 | /* Special Functions */
28 |
29 | /**
30 | * @dev Conversion parameters provide the conversion rate and its scale.
31 | * For example, if 1 value token is equivalent to 3.5 branded
32 | * tokens (1:3.5), _conversionRate == 35 and _conversionRateDecimals == 1.
33 | *
34 | * @param _valueToken The value to which valueToken is set.
35 | * @param _symbol The value to which tokenSymbol, defined in EIP20Token, is set.
36 | * @param _name The value to which tokenName, defined in EIP20Token, is set.
37 | * @param _decimals The value to which tokenDecimals, defined in EIP20Token, is set.
38 | * @param _conversionRate The value to which conversionRate is set.
39 | * @param _conversionRateDecimals The value to which conversionRateDecimals
40 | * is set.
41 | * @param _organization The value to which organization, defined in Organized, is set.
42 | */
43 | constructor(
44 | EIP20Interface _valueToken,
45 | string memory _symbol,
46 | string memory _name,
47 | uint8 _decimals,
48 | uint256 _conversionRate,
49 | uint8 _conversionRateDecimals,
50 | OrganizationInterface _organization
51 | )
52 | BrandedToken(
53 | _valueToken,
54 | _symbol,
55 | _name,
56 | _decimals,
57 | _conversionRate,
58 | _conversionRateDecimals,
59 | _organization
60 | )
61 | public
62 | {}
63 |
64 |
65 | /* External Functions */
66 |
67 | /**
68 | * @notice Mocks BrandedToken requestStake function.
69 | *
70 | * @dev It takes below parameters in order:
71 | * - amount to stake
72 | * - amount to mint
73 | *
74 | * @return Unique hash for each stake request.
75 | */
76 | function requestStake(
77 | uint256,
78 | uint256
79 | )
80 | external
81 | returns (bytes32)
82 | {
83 |
84 | return bytes32(0);
85 | }
86 |
87 | /**
88 | * @notice Mocks BrandedToken acceptStakeRequest function. It fails the execution.
89 | *
90 | * @dev It takes below parameters in order:
91 | * - stake request hash
92 | * - r is the actual signature
93 | * - s is the second point on the curve in order to ecrecover
94 | * - v selects the final public key
95 | */
96 | function acceptStakeRequest(
97 | bytes32,
98 | bytes32,
99 | bytes32,
100 | uint8
101 | )
102 | external
103 | returns (bool)
104 | {
105 | require(false, "BrandedToken acceptStakeRequest returned false.");
106 | }
107 |
108 | /**
109 | * @notice Mocks BrandedToken.revokeStakeRequest() function.
110 | *
111 | * @dev It takes below parameters in order:
112 | * - stake request hash
113 | *
114 | * @return False to replicate failure cases.
115 | */
116 | function revokeStakeRequest(
117 | bytes32
118 | )
119 | external
120 | returns (bool)
121 | {
122 | return false;
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/contracts/test/eip20token/EIP20TokenMockFail.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 |
4 | // Copyright 2019 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 |
19 |
20 |
21 | import "../../EIP20TokenMock.sol";
22 |
23 |
24 | /**
25 | * @title Mock EIP20 Token Fail.
26 | *
27 | * @notice Mocks EIP20 token functions as failing.
28 | */
29 | contract EIP20TokenMockFail is EIP20TokenMock {
30 |
31 | /* Constructor */
32 |
33 | /**
34 | * @param _symbol The value to which tokenSymbol, defined in EIP20Token,
35 | * is set.
36 | * @param _name The value to which tokenName, defined in EIP20Token,
37 | * is set.
38 | * @param _decimals The value to which tokenDecimals, defined in EIP20Token,
39 | * is set.
40 | */
41 | constructor(
42 | string memory _symbol,
43 | string memory _name,
44 | uint8 _decimals
45 | )
46 | EIP20TokenMock(_symbol, _name, _decimals)
47 | public
48 | { }
49 |
50 |
51 | /* External Functions */
52 |
53 | /**
54 | * @notice Mocks failing transferFrom.
55 | *
56 | * @return bool False.
57 | */
58 | function transferFrom(
59 | address,
60 | address,
61 | uint256
62 | )
63 | public
64 | returns (bool)
65 | {
66 | return false;
67 | }
68 | }
--------------------------------------------------------------------------------
/contracts/test/eip20token/EIP20TokenMockPass.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 |
4 | // Copyright 2019 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 |
19 | import "../../EIP20TokenMock.sol";
20 |
21 |
22 | /**
23 | * @title Mock EIP20 Token Pass.
24 | *
25 | * @notice Mocks EIP20 token functions as passing.
26 | */
27 | contract EIP20TokenMockPass is EIP20TokenMock {
28 |
29 | /* Constructor */
30 |
31 | /**
32 | * @param _symbol The value to which tokenSymbol, defined in EIP20Token,
33 | * is set.
34 | * @param _name The value to which tokenName, defined in EIP20Token,
35 | * is set.
36 | * @param _decimals The value to which tokenDecimals, defined in EIP20Token,
37 | * is set.
38 | */
39 | constructor(
40 | string memory _symbol,
41 | string memory _name,
42 | uint8 _decimals
43 | )
44 | EIP20TokenMock(_symbol, _name, _decimals)
45 | public
46 | { }
47 |
48 |
49 | /* External Functions */
50 |
51 | /**
52 | * @notice Mocks passing transferFrom.
53 | *
54 | * @return bool True.
55 | */
56 | function transferFrom(
57 | address,
58 | address,
59 | uint256
60 | )
61 | public
62 | returns (bool)
63 | {
64 | return true;
65 | }
66 |
67 | /**
68 | * @notice Mocks passing transfer.
69 | *
70 | * @return bool True.
71 | */
72 | function transfer(
73 | address,
74 | uint256
75 | )
76 | public
77 | returns (bool)
78 | {
79 | return true;
80 | }
81 | }
--------------------------------------------------------------------------------
/contracts/test/eip20token/EIP20TokenMockPassFail.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 |
4 | // Copyright 2019 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 |
19 | import "../../EIP20TokenMock.sol";
20 |
21 |
22 | /**
23 | * @title Mock EIP20 Token Pass Fail.
24 | *
25 | * @notice Mocks EIP20 token transferFrom as passing and transfer as failing.
26 | * Passing transferFrom but failing transfer enables testing
27 | * functions that invoke transfer but can only be successfully
28 | * called after successfully invoking transferFrom.
29 | */
30 | contract EIP20TokenMockPassFail is EIP20TokenMock {
31 |
32 | /* Constructor */
33 |
34 | /**
35 | * @param _symbol The value to which tokenSymbol, defined in EIP20Token,
36 | * is set.
37 | * @param _name The value to which tokenName, defined in EIP20Token,
38 | * is set.
39 | * @param _decimals The value to which tokenDecimals, defined in EIP20Token,
40 | * is set.
41 | */
42 | constructor(
43 | string memory _symbol,
44 | string memory _name,
45 | uint8 _decimals
46 | )
47 | EIP20TokenMock(_symbol, _name, _decimals)
48 | public
49 | { }
50 |
51 |
52 | /* External Functions */
53 |
54 | /**
55 | * @notice Mocks passing transferFrom.
56 | *
57 | * @dev Passing transferFrom enable
58 | * the signature of a worker, as defined in Organization.
59 | *
60 | * @return bool True.
61 | */
62 | function transferFrom(
63 | address,
64 | address,
65 | uint256
66 | )
67 | public
68 | returns (bool)
69 | {
70 | return true;
71 | }
72 |
73 | /**
74 | * @notice Mocks failing transfer.
75 | *
76 | * @return bool False.
77 | */
78 | function transfer(
79 | address,
80 | uint256
81 | )
82 | public
83 | returns (bool)
84 | {
85 | return false;
86 | }
87 | }
--------------------------------------------------------------------------------
/contracts/test/gateway/MockGatewayFail.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 |
18 | /**
19 | * @title MockGatewayFail contract.
20 | *
21 | * @notice Mocks gateway contract for negative test cases.
22 | */
23 | contract MockGatewayFail {
24 |
25 | /* External Functions */
26 |
27 | /**
28 | * @notice Returns bounty amount.
29 | *
30 | * @return Amount of ERC20 which needs to be staked by facilitator.
31 | */
32 | function bounty()
33 | external
34 | pure
35 | returns (uint256)
36 | {
37 | return 10;
38 | }
39 |
40 | /**
41 | * @notice Mocks gateway.stake. It fails the execution.
42 | *
43 | * @dev parameters are in below order:
44 | * _amount
45 | * _beneficiary
46 | * _gasPrice
47 | * _gasLimit
48 | * _nonce
49 | * _hashLock
50 | *
51 | */
52 | function stake(
53 | uint256,
54 | address,
55 | uint256,
56 | uint256,
57 | uint256,
58 | bytes32
59 | )
60 | pure
61 | external
62 | returns (bytes32)
63 | {
64 | require(false, "Gateway.stake() execution failed.");
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/contracts/test/gateway/MockGatewayPass.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 |
18 | /**
19 | * @title MockGatewayPass contract.
20 | *
21 | * @notice Mocks gateway contract with successful returns.
22 | */
23 | contract MockGatewayPass {
24 |
25 | /* External Functions */
26 |
27 | /**
28 | * @notice Returns bounty amount.
29 | *
30 | * @return Amount of ERC20 which needs to be staked by facilitator.
31 | */
32 | function bounty()
33 | external
34 | pure
35 | returns (uint256)
36 | {
37 | return 0;
38 | }
39 |
40 | /**
41 | * @notice Initiates the stake process. In order to stake the staker
42 | * needs to approve Gateway contract for stake amount.
43 | * Staked amount is transferred from staker address to
44 | * Gateway contract. Bounty amount is also transferred from staker.
45 | *
46 | * @dev parameters are in below order:
47 | * _amount
48 | * _beneficiary
49 | * _gasPrice
50 | * _gasLimit
51 | * _nonce
52 | * _hashLock
53 | *
54 | * @return Message hash unique for each request.
55 | */
56 | function stake(
57 | uint256,
58 | address,
59 | uint256,
60 | uint256,
61 | uint256,
62 | bytes32
63 | )
64 | external
65 | pure
66 | returns (bytes32)
67 | {
68 | return bytes32(0);
69 | }
70 |
71 | /**
72 | * @notice Revert stake process and get the stake
73 | * amount back. Only staker can revert stake by providing
74 | * penalty i.e. 1.5 times of bounty amount. On progress revert stake
75 | * penalty and facilitator bounty will be burned.
76 | *
77 | * @dev The only parameter is _messageHash.
78 | *
79 | * Returns are in below order:
80 | * - staker_
81 | * - stakerNonce_
82 | * - amount_
83 | */
84 | function revertStake(
85 | bytes32
86 | )
87 | external
88 | pure
89 | returns (address, uint256, uint256)
90 | {
91 | return (address(0), uint256(0), uint256(0));
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/contracts/test/organization/OrganizationMockFail.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 |
4 | // Copyright 2019 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 |
19 | /**
20 | * @title Mock Organization Fail.
21 | *
22 | * @notice Mocks Organization functions as failing.
23 | */
24 | contract OrganizationMockFail {
25 |
26 | /* External Functions */
27 |
28 | /**
29 | * @notice Mocks failing isOrganization.
30 | *
31 | * @return bool False.
32 | */
33 | function isOrganization(address)
34 | external
35 | pure
36 | returns (bool)
37 | {
38 | return false;
39 | }
40 |
41 | /**
42 | * @notice Mocks failing isWorker.
43 | *
44 | * @return bool False.
45 | */
46 | function isWorker(address)
47 | external
48 | pure
49 | returns (bool)
50 | {
51 | return false;
52 | }
53 | }
--------------------------------------------------------------------------------
/contracts/test/organization/OrganizationMockPass.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 |
4 | // Copyright 2019 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 |
19 | /**
20 | * @title Organization Mock Pass.
21 | *
22 | * @notice Mocks Organization functions as passing.
23 | */
24 | contract OrganizationMockPass {
25 |
26 | /* External Functions */
27 |
28 | /**
29 | * @notice Mocks passing isOrganization.
30 | *
31 | * @return bool True.
32 | */
33 | function isOrganization(address)
34 | external
35 | pure
36 | returns (bool)
37 | {
38 | return true;
39 | }
40 |
41 | /**
42 | * @notice Mocks passing isWorker.
43 | *
44 | * @return bool True.
45 | */
46 | function isWorker(address)
47 | external
48 | pure
49 | returns (bool)
50 | {
51 | return true;
52 | }
53 | }
--------------------------------------------------------------------------------
/contracts/test/organization/OrganizationMockWorker.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 |
4 | // Copyright 2019 OpenST Ltd.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 |
19 | /**
20 | * @title Organization Mock Worker.
21 | *
22 | * @notice Mocks Organization setWorker and isWorker functions.
23 | */
24 | contract OrganizationMockWorker {
25 |
26 | address public worker;
27 |
28 | /* External Functions */
29 |
30 | /**
31 | * @notice Mocks setWorker.
32 | *
33 | * @param _worker The value to which worker is set.
34 | */
35 | function setWorker(
36 | address _worker,
37 | uint256
38 | )
39 | external
40 | {
41 | worker = _worker;
42 | }
43 |
44 | /**
45 | * @notice Mocks isWorker.
46 | *
47 | * @return bool True if worker == _worker, false if not.
48 | */
49 | function isWorker(
50 | address _worker
51 | )
52 | external
53 | view
54 | returns (bool)
55 | {
56 | return worker == _worker;
57 | }
58 | }
--------------------------------------------------------------------------------
/contracts/truffle/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | contract Migrations {
4 |
5 | address public owner;
6 | uint public last_completed_migration;
7 |
8 | modifier restricted() {
9 | if (msg.sender == owner) _;
10 | }
11 |
12 | constructor() public {
13 | owner = msg.sender;
14 | }
15 |
16 | function setCompleted(uint completed) public restricted {
17 | last_completed_migration = completed;
18 | }
19 |
20 | function upgrade(address new_address) public restricted {
21 | Migrations upgraded = Migrations(new_address);
22 | upgraded.setCompleted(last_completed_migration);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // ----------------------------------------------------------------------------
16 | //
17 | // http://www.simpletoken.org/
18 | //
19 | // ----------------------------------------------------------------------------
20 |
21 | const contracts = require('./contracts.json');
22 |
23 | module.exports = contracts;
24 |
--------------------------------------------------------------------------------
/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | const Migrations = artifacts.require('./Migrations.sol');
2 |
3 | module.exports = (deployer) => {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@openst/brandedtoken-contracts",
3 | "version": "0.10.0",
4 | "description": "BrandedToken Contracts provides token and related smart contracts for token economies.",
5 | "keywords": [
6 | "OpenST",
7 | "OST",
8 | "Simple Token",
9 | "Token Economy",
10 | "Ethereum",
11 | "EIP20",
12 | "Branded Token"
13 | ],
14 | "homepage": "https://openst.org",
15 | "author": "OpenST Limited",
16 | "license": "Apache-2.0",
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/OpenST/brandedtoken-contracts.git"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/OpenST/brandedtoken-contracts/issues"
23 | },
24 | "scripts": {
25 | "build-package": "node tools/build_package.js",
26 | "compile-all": "truffle compile --all",
27 | "test": "truffle test",
28 | "test:range": "./tools/test_range.sh",
29 | "prepack": "npm run compile-all && npm run build-package",
30 | "lint": "eslint migrations/*.js test/*/*.js tools/*.js -c .eslintrc"
31 | },
32 | "main": "dist/index.js",
33 | "files": [
34 | "dist"
35 | ],
36 | "devDependencies": {
37 | "abi-decoder": "1.2.0",
38 | "assert": "1.4.1",
39 | "bignumber.js": "4.1.0",
40 | "bn.js": "4.11.8",
41 | "eslint": "^5.16.0",
42 | "eslint-config-airbnb-base": "13.1.0",
43 | "eslint-plugin-import": "2.14.0",
44 | "ethereumjs-util": "5.2.0",
45 | "ganache-cli": "6.4.3",
46 | "solidity-coverage": "0.5.11",
47 | "truffle": "5.0.19",
48 | "web3": "1.0.0-beta.36",
49 | "openzeppelin-solidity": "2.1.1"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/test/branded_token/accept_stake_request.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const EthUtils = require('ethereumjs-util');
20 | const { AccountProvider } = require('../test_lib/utils.js');
21 | const { Event } = require('../test_lib/event_decoder.js');
22 |
23 | const web3 = require('../test_lib/web3.js');
24 | const utils = require('../test_lib/utils');
25 | const brandedTokenUtils = require('./utils');
26 | const config = require('../test_lib/config');
27 |
28 | const BrandedToken = artifacts.require('BrandedToken');
29 | const EIP20TokenMockPass = artifacts.require('EIP20TokenMockPass');
30 | const OrganizationMockWorker = artifacts.require('OrganizationMockWorker');
31 |
32 | contract('BrandedToken::acceptStakeRequest', async () => {
33 | const r = web3.utils.soliditySha3('r');
34 | const s = web3.utils.soliditySha3('s');
35 | const v = 0;
36 |
37 | contract('Negative Tests', async (accounts) => {
38 | const accountProvider = new AccountProvider(accounts);
39 |
40 | it('Reverts if stake request not found', async () => {
41 | const {
42 | brandedToken,
43 | } = await brandedTokenUtils.setupBrandedToken(
44 | accountProvider,
45 | );
46 |
47 | const worker = accountProvider.get();
48 | const stakeRequestHash = web3.utils.utf8ToHex('stakeRequestHash');
49 |
50 | await utils.expectRevert(
51 | brandedToken.acceptStakeRequest(
52 | stakeRequestHash,
53 | r,
54 | s,
55 | v,
56 | { from: worker },
57 | ),
58 | 'Should revert as stake request not found.',
59 | 'Stake request not found.',
60 | );
61 | });
62 |
63 | it('Reverts if signer is not a worker', async () => {
64 | const {
65 | brandedToken,
66 | stakeRequestHash,
67 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
68 | accountProvider,
69 | false, // Use OrganizationMockFail
70 | );
71 |
72 | const worker = accountProvider.get();
73 |
74 | await utils.expectRevert(
75 | brandedToken.acceptStakeRequest(
76 | stakeRequestHash,
77 | r,
78 | s,
79 | v,
80 | { from: worker },
81 | ),
82 | 'Should revert as signer is not a worker.',
83 | 'Signer is not a worker.',
84 | );
85 | });
86 | });
87 |
88 | contract('Event', async (accounts) => {
89 | const accountProvider = new AccountProvider(accounts);
90 |
91 | it('Emits StakeRequestAccepted and Transfer events', async () => {
92 | const {
93 | brandedToken,
94 | staker,
95 | stake,
96 | stakeRequestHash,
97 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
98 | accountProvider,
99 | );
100 |
101 | const worker = accountProvider.get();
102 |
103 | const transactionResponse = await brandedToken.acceptStakeRequest(
104 | stakeRequestHash,
105 | r,
106 | s,
107 | v,
108 | { from: worker },
109 | );
110 |
111 | const mint = await brandedToken.convertToBrandedTokens(stake);
112 |
113 | const events = Event.decodeTransactionResponse(
114 | transactionResponse,
115 | );
116 |
117 | assert.strictEqual(
118 | events.length,
119 | 2,
120 | );
121 |
122 | Event.assertEqual(events[0], {
123 | name: 'StakeRequestAccepted',
124 | args: {
125 | _stakeRequestHash: stakeRequestHash,
126 | _staker: staker,
127 | _stake: new BN(stake),
128 | },
129 | });
130 |
131 | Event.assertEqual(events[1], {
132 | name: 'Transfer',
133 | args: {
134 | _from: utils.NULL_ADDRESS,
135 | _to: staker,
136 | _value: mint,
137 | },
138 | });
139 | });
140 | });
141 |
142 | contract('Storage', async (accounts) => {
143 | const accountProvider = new AccountProvider(accounts);
144 |
145 | it('Successfully mints branded tokens', async () => {
146 | const {
147 | brandedToken,
148 | staker,
149 | stake,
150 | stakeRequestHash,
151 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
152 | accountProvider,
153 | );
154 |
155 | // N.B.: anyone can call acceptStakeRequest
156 | const worker = accountProvider.get();
157 |
158 | // Contract does not confirm that address returned from ecrecover
159 | // is not a 0 address. Consequently, signature components
160 | // that return a 0 address are OK so long as
161 | // Organization.isWorker returns true for a 0 address
162 | assert.isOk(
163 | await brandedToken.acceptStakeRequest.call(
164 | stakeRequestHash,
165 | r,
166 | s,
167 | v,
168 | { from: worker },
169 | ),
170 | );
171 |
172 | await brandedToken.acceptStakeRequest(
173 | stakeRequestHash,
174 | r,
175 | s,
176 | v,
177 | { from: worker },
178 | );
179 |
180 | const mint = await brandedToken.convertToBrandedTokens(stake);
181 |
182 | assert.strictEqual(
183 | mint.cmp(
184 | await brandedToken.balanceOf(staker),
185 | ),
186 | 0,
187 | );
188 |
189 | assert.strictEqual(
190 | mint.cmp(
191 | await brandedToken.totalSupply(),
192 | ),
193 | 0,
194 | );
195 | });
196 |
197 | it('Verifies stake request hash signer', async () => {
198 | // Setup organization
199 | const organization = await OrganizationMockWorker.new();
200 | const worker = accountProvider.get();
201 | const valueToken = await EIP20TokenMockPass.new(
202 | 'VT',
203 | 'ValueToken',
204 | config.decimals,
205 | );
206 |
207 | await organization.setWorker(worker, 0);
208 |
209 | // Setup brandedToken
210 | const brandedToken = await BrandedToken.new(
211 | valueToken.address,
212 | 'BT',
213 | 'BrandedToken',
214 | config.decimals,
215 | 35,
216 | 1,
217 | organization.address,
218 | );
219 |
220 | // Request stake
221 | const stake = 1;
222 | const mint = await brandedToken.convertToBrandedTokens(stake);
223 | const staker = accountProvider.get();
224 |
225 | await brandedToken.requestStake(
226 | stake,
227 | mint,
228 | { from: staker },
229 | );
230 |
231 | const EIP712_DOMAIN_TYPEHASH = web3.utils.soliditySha3(
232 | 'EIP712Domain(address verifyingContract)',
233 | );
234 | const DOMAIN_SEPARATOR = web3.utils.soliditySha3(
235 | web3.eth.abi.encodeParameters(
236 | ['bytes32', 'address'],
237 | [EIP712_DOMAIN_TYPEHASH, brandedToken.address],
238 | ),
239 | );
240 | const stakeRequestHash = await brandedToken.stakeRequestHashes(staker);
241 |
242 | // Prepare and sign typed data, for example see:
243 | // https://github.com/ethereum/EIPs/blob/master/assets/eip-712/Example.js
244 | // N.B.: below differs from the example due to sha3's deprecation. See:
245 | // https://github.com/ethereumjs/ethereumjs-util/blob/master/CHANGELOG.md#600---2018-10-08
246 | const typedDataToSign = EthUtils.keccak(
247 | Buffer.concat(
248 | [
249 | Buffer.from('19', 'hex'),
250 | Buffer.from('01', 'hex'),
251 | EthUtils.toBuffer(DOMAIN_SEPARATOR),
252 | EthUtils.toBuffer(stakeRequestHash),
253 | ],
254 | ),
255 | );
256 | const privateKey = EthUtils.keccak('signer');
257 | const signer = EthUtils.privateToAddress(privateKey);
258 | const signature = EthUtils.ecsign(
259 | typedDataToSign,
260 | privateKey,
261 | );
262 |
263 | // Set signer as a worker
264 | await organization.setWorker(EthUtils.bufferToHex(signer), 0);
265 |
266 | // Fails with incorrect signature components
267 | await utils.expectRevert(
268 | brandedToken.acceptStakeRequest(
269 | stakeRequestHash,
270 | signature.r, // correct
271 | signature.s, // correct
272 | 0, // incorrect
273 | { from: worker },
274 | ),
275 | 'Should revert as signer is not a worker.',
276 | 'Signer is not a worker.',
277 | );
278 |
279 | // Passes with correct signature components
280 | assert.isOk(
281 | await brandedToken.acceptStakeRequest.call(
282 | stakeRequestHash,
283 | signature.r,
284 | signature.s,
285 | signature.v,
286 | { from: worker },
287 | ),
288 | );
289 | });
290 | });
291 | });
292 |
--------------------------------------------------------------------------------
/test/branded_token/constructor.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 |
21 | const config = require('../test_lib/config');
22 | const utils = require('../test_lib/utils');
23 |
24 | const BrandedToken = artifacts.require('BrandedToken');
25 | const EIP20TokenMock = artifacts.require('EIP20TokenMock');
26 |
27 | /**
28 | * Deploys an EIP20TokenMock contract with the provided decimals.
29 | * @param {number} decimals Decimals for token.
30 | * @return {string} valueToken Address of token.
31 | */
32 | const deployValueToken = async (decimals) => {
33 | const { address: valueToken } = await EIP20TokenMock.new(
34 | 'VT',
35 | 'ValueToken',
36 | decimals,
37 | );
38 |
39 | return valueToken;
40 | };
41 |
42 | contract('BrandedToken::constructor', async () => {
43 | contract('Negative Tests', async (accounts) => {
44 | const accountProvider = new AccountProvider(accounts);
45 |
46 | const symbol = 'BT';
47 | const name = 'BrandedToken';
48 | const { decimals } = config;
49 | const organization = accountProvider.get();
50 |
51 | it('Reverts if valueToken is zero', async () => {
52 | const valueToken = utils.NULL_ADDRESS;
53 | const conversionRate = 35;
54 | const conversionRateDecimals = 1;
55 |
56 | await utils.expectRevert(
57 | BrandedToken.new(
58 | valueToken,
59 | symbol,
60 | name,
61 | decimals,
62 | conversionRate,
63 | conversionRateDecimals,
64 | organization,
65 | ),
66 | 'Should revert as valueToken is zero.',
67 | 'ValueToken is zero.',
68 | );
69 | });
70 |
71 | it('Reverts if valueToken decimals does not equal brandedToken decimals', async () => {
72 | const valueToken = await deployValueToken(decimals + 1);
73 |
74 | const conversionRate = 35;
75 | const conversionRateDecimals = 1;
76 |
77 | await utils.expectRevert(
78 | BrandedToken.new(
79 | valueToken,
80 | symbol,
81 | name,
82 | decimals,
83 | conversionRate,
84 | conversionRateDecimals,
85 | organization,
86 | ),
87 | 'Should revert as valueToken decimals does not equal brandedToken decimals.',
88 | 'ValueToken decimals does not equal brandedToken decimals.',
89 | );
90 | });
91 |
92 | it('Reverts if conversionRate is zero', async () => {
93 | const valueToken = await deployValueToken(decimals);
94 |
95 | const conversionRate = 0;
96 | const conversionRateDecimals = 1;
97 |
98 | await utils.expectRevert(
99 | BrandedToken.new(
100 | valueToken,
101 | symbol,
102 | name,
103 | decimals,
104 | conversionRate,
105 | conversionRateDecimals,
106 | organization,
107 | ),
108 | 'Should revert as conversionRate is zero.',
109 | 'ConversionRate is zero.',
110 | );
111 | });
112 |
113 | it('Reverts if conversionRateDecimals is greater than 5', async () => {
114 | const valueToken = await deployValueToken(decimals);
115 |
116 | const conversionRate = 35;
117 | const conversionRateDecimals = 6;
118 |
119 | await utils.expectRevert(
120 | BrandedToken.new(
121 | valueToken,
122 | symbol,
123 | name,
124 | decimals,
125 | conversionRate,
126 | conversionRateDecimals,
127 | organization,
128 | ),
129 | 'Should revert as conversionRateDecimals is greater than 5.',
130 | 'ConversionRateDecimals is greater than 5.',
131 | );
132 | });
133 | });
134 |
135 | contract('Storage', async (accounts) => {
136 | const accountProvider = new AccountProvider(accounts);
137 |
138 | const symbol = 'BT';
139 | const name = 'BrandedToken';
140 | const { decimals } = config;
141 | const organization = accountProvider.get();
142 |
143 | it('Successfully sets state variables', async () => {
144 | const valueToken = await deployValueToken(decimals);
145 |
146 | const conversionRate = 35;
147 | const conversionRateDecimals = 1;
148 |
149 | const brandedToken = await BrandedToken.new(
150 | valueToken,
151 | symbol,
152 | name,
153 | decimals,
154 | conversionRate,
155 | conversionRateDecimals,
156 | organization,
157 | );
158 |
159 | assert.strictEqual(
160 | (await brandedToken.valueToken()),
161 | valueToken,
162 | );
163 |
164 | assert.strictEqual(
165 | (await brandedToken.conversionRate()).cmp(
166 | new BN(conversionRate),
167 | ),
168 | 0,
169 | );
170 |
171 | assert.strictEqual(
172 | (await brandedToken.conversionRateDecimals()).cmp(
173 | new BN(conversionRateDecimals),
174 | ),
175 | 0,
176 | );
177 | });
178 | });
179 | });
180 |
--------------------------------------------------------------------------------
/test/branded_token/convert_to_branded_tokens.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const BrandedTokenUtils = require('./utils.js');
21 |
22 | contract('BrandedToken::convertToBrandedTokens', async () => {
23 | contract('Returns', async (accounts) => {
24 | it('Correctly converts to branded tokens', async () => {
25 | const accountProvider = new AccountProvider(accounts);
26 |
27 | const {
28 | brandedToken,
29 | } = await BrandedTokenUtils.setupBrandedToken(
30 | accountProvider,
31 | );
32 |
33 | const conversionRate = await brandedToken.conversionRate();
34 | const conversionRateDecimals = await brandedToken.conversionRateDecimals();
35 |
36 | // Conversion without loss
37 | // Depending on the conversion rate, some amounts
38 | // converts without loss; e.g., when conversion is 1:3.5
39 | // - conversionRate == 35
40 | // - conversionRateDecimals == 1
41 | // - 2 --> 7
42 | const valueTokensLossless = new BN(2);
43 | const brandedTokensLossless = await brandedToken
44 | .convertToBrandedTokens(valueTokensLossless);
45 |
46 | assert.strictEqual(
47 | brandedTokensLossless.cmp(
48 | valueTokensLossless
49 | .mul(conversionRate)
50 | .div(new BN(10).pow(conversionRateDecimals)),
51 | ),
52 | 0,
53 | );
54 |
55 | assert.strictEqual(
56 | brandedTokensLossless.cmp(
57 | new BN(7),
58 | ),
59 | 0,
60 | );
61 |
62 | // Conversion with loss
63 | // At other amounts of value tokens, there will be loss
64 | // due to Solidity not supportin fixed or floating point
65 | // math; e.g., when conversion is 1:3.5
66 | // - conversionRate == 35
67 | // - conversionRateDecimals == 1
68 | // - 1 --> 3, not 3.5
69 | const valueTokensLoss = new BN(1);
70 | const brandedTokensLoss = await brandedToken
71 | .convertToBrandedTokens(valueTokensLoss);
72 |
73 | assert.strictEqual(
74 | brandedTokensLoss.cmp(
75 | valueTokensLoss
76 | .mul(conversionRate)
77 | .div(new BN(10).pow(conversionRateDecimals)),
78 | ),
79 | 0,
80 | );
81 |
82 | // 1 converts to 3, not 3.5, so there is a loss
83 | assert.strictEqual(
84 | brandedTokensLoss.cmp(
85 | new BN(3),
86 | ),
87 | 0,
88 | );
89 |
90 | // N.B.: the potential for and degree of loss
91 | // as indicated above is considered acceptable,
92 | // depending on the number of decimal places (e.g., 18)
93 | });
94 | });
95 | });
96 |
--------------------------------------------------------------------------------
/test/branded_token/convert_to_value_tokens.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const BrandedTokenUtils = require('./utils.js');
21 |
22 | contract('BrandedToken::convertToValueTokens', async () => {
23 | contract('Returns', async (accounts) => {
24 | it('Correctly converts to value tokens', async () => {
25 | const accountProvider = new AccountProvider(accounts);
26 |
27 | const {
28 | brandedToken,
29 | } = await BrandedTokenUtils.setupBrandedToken(
30 | accountProvider,
31 | );
32 |
33 | const conversionRate = await brandedToken.conversionRate();
34 | const conversionRateDecimals = await brandedToken.conversionRateDecimals();
35 |
36 | // Conversion without loss
37 | // An amount equal to multiples of the conversionRate
38 | // converts without loss; e.g., when conversion is 1:3.5
39 | // - conversionRate == 35
40 | // - conversionRateDecimals == 1
41 | // - 35 --> 10
42 | const brandedTokensLossless = conversionRate;
43 | const valueTokensLossless = await brandedToken
44 | .convertToValueTokens(brandedTokensLossless);
45 |
46 | assert.strictEqual(
47 | valueTokensLossless.cmp(
48 | brandedTokensLossless
49 | .mul(new BN(10).pow(conversionRateDecimals))
50 | .div(conversionRate),
51 | ),
52 | 0,
53 | );
54 |
55 | assert.strictEqual(
56 | valueTokensLossless.cmp(
57 | new BN(10),
58 | ),
59 | 0,
60 | );
61 |
62 | // Conversion with loss
63 | // At other amounts of branded tokens there will be loss
64 | // due to Solidity not supportin fixed or floating point
65 | // math; e.g., when conversion is 1:3.5
66 | // - conversionRate == 35
67 | // - conversionRateDecimals == 1
68 | // - 36 --> 10 value tokens, not 10.2
69 | const brandedTokensLoss = conversionRate.addn(1);
70 | const valueTokensLoss = await brandedToken
71 | .convertToValueTokens(brandedTokensLoss);
72 |
73 | assert.strictEqual(
74 | valueTokensLoss.cmp(
75 | brandedTokensLoss
76 | .mul(new BN(10).pow(conversionRateDecimals))
77 | .div(conversionRate),
78 | ),
79 | 0,
80 | );
81 |
82 | // 36 also converts into 10 so there is a loss in the conversion
83 | assert.strictEqual(
84 | valueTokensLoss.cmp(
85 | new BN(10),
86 | ),
87 | 0,
88 | );
89 |
90 | // N.B.: the potential for and degree of loss
91 | // as indicated above is considered acceptable,
92 | // depending on the number of decimal places (e.g., 18)
93 | });
94 | });
95 | });
96 |
--------------------------------------------------------------------------------
/test/branded_token/lift_all_restrictions.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const { AccountProvider } = require('../test_lib/utils.js');
19 |
20 | const utils = require('../test_lib/utils');
21 | const brandedTokenUtils = require('./utils');
22 |
23 | contract('BrandedToken::liftAllRestrictions', async () => {
24 | contract('Negative Tests', async (accounts) => {
25 | const accountProvider = new AccountProvider(accounts);
26 |
27 | it('Reverts if msg.sender is not the organization', async () => {
28 | const {
29 | brandedToken,
30 | } = await brandedTokenUtils.setupBrandedToken(
31 | accountProvider,
32 | false,
33 | );
34 |
35 | const nonOrganization = accountProvider.get();
36 |
37 | await utils.expectRevert(
38 | brandedToken.liftAllRestrictions(
39 | { from: nonOrganization },
40 | ),
41 | 'Should revert as msg.sender is not the organization.',
42 | 'Only the organization is allowed to call this method.',
43 | );
44 | });
45 | });
46 |
47 | contract('Storage', async (accounts) => {
48 | const accountProvider = new AccountProvider(accounts);
49 |
50 | it('Successfully lifts all restrictions', async () => {
51 | const {
52 | brandedToken,
53 | staker,
54 | worker,
55 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
56 | accountProvider,
57 | );
58 |
59 | const to = accountProvider.get();
60 | const brandedTokens = 1;
61 |
62 | await utils.expectRevert(
63 | brandedToken.transfer(
64 | to,
65 | brandedTokens,
66 | { from: staker },
67 | ),
68 | 'Should revert as msg.sender is restricted.',
69 | 'Msg.sender is restricted.',
70 | );
71 |
72 | assert.isOk(
73 | await brandedToken.liftAllRestrictions.call(
74 | { from: worker },
75 | ),
76 | );
77 |
78 | await brandedToken.liftAllRestrictions(
79 | { from: worker },
80 | );
81 |
82 | assert.isNotOk(
83 | await brandedToken.isUnrestricted(
84 | staker,
85 | { from: worker },
86 | ),
87 | );
88 |
89 | await brandedToken.transfer(
90 | to,
91 | brandedTokens,
92 | { from: staker },
93 | );
94 | });
95 | });
96 | });
97 |
--------------------------------------------------------------------------------
/test/branded_token/lift_restriction.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const { AccountProvider } = require('../test_lib/utils.js');
19 |
20 | const utils = require('../test_lib/utils');
21 | const brandedTokenUtils = require('./utils');
22 |
23 | contract('BrandedToken::liftRestriction', async () => {
24 | contract('Negative Tests', async (accounts) => {
25 | const accountProvider = new AccountProvider(accounts);
26 |
27 | it('Reverts if msg.sender is not a worker', async () => {
28 | const {
29 | brandedToken,
30 | } = await brandedTokenUtils.setupBrandedToken(
31 | accountProvider,
32 | false,
33 | );
34 |
35 | const restrictionLifted = [accountProvider.get()];
36 | const nonWorker = accountProvider.get();
37 |
38 | await utils.expectRevert(
39 | brandedToken.liftRestriction(
40 | restrictionLifted,
41 | { from: nonWorker },
42 | ),
43 | 'Should revert as msg.sender is not a worker.',
44 | 'Only whitelisted workers are allowed to call this method.',
45 | );
46 | });
47 | });
48 |
49 | contract('Storage', async (accounts) => {
50 | const accountProvider = new AccountProvider(accounts);
51 |
52 | it('Successfully lifts restrictions', async () => {
53 | const {
54 | brandedToken,
55 | } = await brandedTokenUtils.setupBrandedToken(
56 | accountProvider,
57 | );
58 |
59 | const restrictionLifted = [accountProvider.get(), accountProvider.get()];
60 | const worker = accountProvider.get();
61 |
62 | assert.isOk(
63 | await brandedToken.liftRestriction.call(
64 | restrictionLifted,
65 | { from: worker },
66 | ),
67 | );
68 |
69 | await brandedToken.liftRestriction(
70 | restrictionLifted,
71 | { from: worker },
72 | );
73 |
74 | /* eslint-disable no-restricted-syntax, no-await-in-loop */
75 | for (const actor of restrictionLifted) {
76 | assert.isOk(
77 | await brandedToken.isUnrestricted(
78 | actor,
79 | ),
80 | );
81 | }
82 | /* eslint-enable no-restricted-syntax, no-await-in-loop */
83 | });
84 | });
85 | });
86 |
--------------------------------------------------------------------------------
/test/branded_token/redeem.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 |
22 | const utils = require('../test_lib/utils');
23 | const brandedTokenUtils = require('./utils');
24 |
25 | contract('BrandedToken::redeem', async () => {
26 | contract('Negative Tests', async (accounts) => {
27 | const accountProvider = new AccountProvider(accounts);
28 |
29 | it('Fails if valueToken.transfer returns false', async () => {
30 | const {
31 | brandedToken,
32 | } = await brandedTokenUtils.setupBrandedToken(
33 | accountProvider,
34 | true,
35 | false, // Use EIP20TokenMockPassFail
36 | );
37 |
38 | await utils.expectRevert(
39 | brandedToken.redeem(
40 | 0,
41 | { from: accountProvider.get() },
42 | ),
43 | 'Should revert as valueToken.transfer returned false.',
44 | 'ValueToken.transfer returned false.',
45 | );
46 | });
47 | });
48 |
49 | contract('Event', async (accounts) => {
50 | const accountProvider = new AccountProvider(accounts);
51 |
52 | it('Emits Redeemed and Transfer events', async () => {
53 | const {
54 | brandedToken,
55 | staker,
56 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
57 | accountProvider,
58 | );
59 |
60 | // At a conversion rate of 3.5, 4 branded tokens (least divisible unit)
61 | // evaluates to 1 value token (least divisible unit)
62 | const brandedTokens = 4;
63 |
64 | const transactionResponse = await brandedToken.redeem(
65 | brandedTokens,
66 | { from: staker },
67 | );
68 |
69 | const events = Event.decodeTransactionResponse(
70 | transactionResponse,
71 | );
72 |
73 | assert.strictEqual(
74 | events.length,
75 | 2,
76 | );
77 |
78 | Event.assertEqual(events[0], {
79 | name: 'Redeemed',
80 | args: {
81 | _redeemer: staker,
82 | _valueTokens: await brandedToken.convertToValueTokens(brandedTokens),
83 | },
84 | });
85 |
86 | Event.assertEqual(events[1], {
87 | name: 'Transfer',
88 | args: {
89 | _from: staker,
90 | _to: utils.NULL_ADDRESS,
91 | _value: new BN(brandedTokens),
92 | },
93 | });
94 | });
95 | });
96 |
97 | contract('Storage', async (accounts) => {
98 | const accountProvider = new AccountProvider(accounts);
99 |
100 | it('Successfully redeems branded tokens', async () => {
101 | const {
102 | brandedToken,
103 | staker,
104 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
105 | accountProvider,
106 | );
107 |
108 | // At a conversion rate of 3.5, 4 branded tokens (least divisible unit)
109 | // evaluates to 1 value token (least divisible unit)
110 | const brandedTokens = 4;
111 | const totalSupplyBefore = await brandedToken.totalSupply();
112 | const balanceBefore = await brandedToken.balanceOf(staker);
113 |
114 | assert.isOk(
115 | await brandedToken.redeem.call(
116 | brandedTokens,
117 | { from: staker },
118 | ),
119 | );
120 |
121 | await brandedToken.redeem(
122 | brandedTokens,
123 | { from: staker },
124 | );
125 |
126 | const totalSupplyAfter = await brandedToken.totalSupply();
127 | const balanceAfter = await brandedToken.balanceOf(staker);
128 |
129 | assert.strictEqual(
130 | totalSupplyAfter.cmp(
131 | totalSupplyBefore.subn(brandedTokens),
132 | ),
133 | 0,
134 | );
135 |
136 | assert.strictEqual(
137 | balanceAfter.cmp(
138 | balanceBefore.subn(brandedTokens),
139 | ),
140 | 0,
141 | );
142 | });
143 | });
144 | });
145 |
--------------------------------------------------------------------------------
/test/branded_token/reject_stake_request.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 |
22 | const web3 = require('../test_lib/web3.js');
23 | const utils = require('../test_lib/utils');
24 | const brandedTokenUtils = require('./utils');
25 |
26 | contract('BrandedToken::rejectStakeRequest', async () => {
27 | contract('Negative Tests', async (accounts) => {
28 | const accountProvider = new AccountProvider(accounts);
29 |
30 | it('Reverts if msg.sender is not a worker', async () => {
31 | const {
32 | brandedToken,
33 | stakeRequestHash,
34 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
35 | accountProvider,
36 | false, // Use OrganizationMockFail
37 | );
38 |
39 | const nonWorker = accountProvider.get();
40 |
41 | await utils.expectRevert(
42 | brandedToken.rejectStakeRequest(
43 | stakeRequestHash,
44 | { from: nonWorker },
45 | ),
46 | 'Should revert as msg.sender is not a worker.',
47 | 'Only whitelisted workers are allowed to call this method.',
48 | );
49 | });
50 |
51 | it('Reverts if stake request not found', async () => {
52 | const {
53 | brandedToken,
54 | } = await brandedTokenUtils.setupBrandedToken(
55 | accountProvider,
56 | );
57 |
58 | const worker = accountProvider.get();
59 | const stakeRequestHash = web3.utils.utf8ToHex('stakeRequestHash');
60 |
61 | await utils.expectRevert(
62 | brandedToken.rejectStakeRequest(
63 | stakeRequestHash,
64 | { from: worker },
65 | ),
66 | 'Should revert as stake request not found.',
67 | 'Stake request not found.',
68 | );
69 | });
70 |
71 | it('Reverts if valueToken.transfer returns false', async () => {
72 | const {
73 | brandedToken,
74 | stakeRequestHash,
75 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
76 | accountProvider,
77 | true,
78 | false, // Use EIP20TokenMockPassFail
79 | );
80 |
81 | const worker = accountProvider.get();
82 |
83 | await utils.expectRevert(
84 | brandedToken.rejectStakeRequest(
85 | stakeRequestHash,
86 | { from: worker },
87 | ),
88 | 'Should revert as valueToken.transfer returned false.',
89 | 'ValueToken.transfer returned false.',
90 | );
91 | });
92 | });
93 |
94 | contract('Event', async (accounts) => {
95 | const accountProvider = new AccountProvider(accounts);
96 |
97 | it('Emits StakeRequestRejected', async () => {
98 | const {
99 | brandedToken,
100 | staker,
101 | stake,
102 | stakeRequestHash,
103 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
104 | accountProvider,
105 | );
106 |
107 | const worker = accountProvider.get();
108 |
109 | const transactionResponse = await brandedToken.rejectStakeRequest(
110 | stakeRequestHash,
111 | { from: worker },
112 | );
113 |
114 | const events = Event.decodeTransactionResponse(
115 | transactionResponse,
116 | );
117 |
118 | assert.strictEqual(
119 | events.length,
120 | 1,
121 | );
122 |
123 | Event.assertEqual(events[0], {
124 | name: 'StakeRequestRejected',
125 | args: {
126 | _stakeRequestHash: stakeRequestHash,
127 | _staker: staker,
128 | _stake: new BN(stake),
129 | },
130 | });
131 | });
132 | });
133 |
134 | contract('Storage', async (accounts) => {
135 | const accountProvider = new AccountProvider(accounts);
136 |
137 | it('Successfully revokes stake request', async () => {
138 | const {
139 | brandedToken,
140 | staker,
141 | stakeRequestHash,
142 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
143 | accountProvider,
144 | );
145 |
146 | const worker = accountProvider.get();
147 |
148 | assert.isOk(
149 | await brandedToken.rejectStakeRequest.call(
150 | stakeRequestHash,
151 | { from: worker },
152 | ),
153 | );
154 |
155 | await brandedToken.rejectStakeRequest(
156 | stakeRequestHash,
157 | { from: worker },
158 | );
159 |
160 | assert.strictEqual(
161 | await brandedToken.stakeRequestHashes(staker),
162 | utils.NULL_BYTES32,
163 | );
164 |
165 | const stakeRequest = await brandedToken.stakeRequests(stakeRequestHash);
166 |
167 | assert.strictEqual(
168 | stakeRequest.staker,
169 | utils.NULL_ADDRESS,
170 | );
171 |
172 | assert.strictEqual(
173 | stakeRequest.stake.cmp(
174 | new BN(0),
175 | ),
176 | 0,
177 | );
178 |
179 | assert.strictEqual(
180 | stakeRequest.nonce.cmp(
181 | new BN(0),
182 | ),
183 | 0,
184 | );
185 | });
186 | });
187 | });
188 |
--------------------------------------------------------------------------------
/test/branded_token/request_stake.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 |
22 | const web3 = require('../test_lib/web3.js');
23 | const utils = require('../test_lib/utils');
24 | const brandedTokenUtils = require('./utils');
25 | const config = require('../test_lib/config');
26 |
27 | const BrandedToken = artifacts.require('BrandedToken');
28 | const EIP20TokenMockFail = artifacts.require('EIP20TokenMockFail');
29 |
30 | contract('BrandedToken::requestStake', async () => {
31 | contract('Negative Tests', async (accounts) => {
32 | const accountProvider = new AccountProvider(accounts);
33 |
34 | it('Reverts if mint is not equivalent to stake', async () => {
35 | const {
36 | brandedToken,
37 | } = await brandedTokenUtils.setupBrandedToken(
38 | accountProvider,
39 | );
40 |
41 | const stake = 1;
42 | const mint = 0;
43 | const staker = accountProvider.get();
44 |
45 | await utils.expectRevert(
46 | brandedToken.requestStake(
47 | stake,
48 | mint,
49 | { from: staker },
50 | ),
51 | 'Should revert as mint is not equivalent to stake.',
52 | 'Mint is not equivalent to stake.',
53 | );
54 | });
55 |
56 | it('Reverts if staker has a stake request hash', async () => {
57 | const {
58 | brandedToken,
59 | } = await brandedTokenUtils.setupBrandedToken(
60 | accountProvider,
61 | );
62 |
63 | const stake = 1;
64 | const mint = await brandedToken.convertToBrandedTokens(stake);
65 | const staker = accountProvider.get();
66 |
67 | await brandedToken.requestStake(
68 | stake,
69 | mint,
70 | { from: staker },
71 | );
72 |
73 | await utils.expectRevert(
74 | brandedToken.requestStake(
75 | stake,
76 | mint,
77 | { from: staker },
78 | ),
79 | 'Should revert as staker has a stake request hash.',
80 | 'Staker has a stake request hash.',
81 | );
82 | });
83 |
84 | it('Reverts if valueToken.transferFrom returns false', async () => {
85 | const valueToken = await EIP20TokenMockFail.new(
86 | 'VT',
87 | 'ValueToken',
88 | config.decimals,
89 | );
90 |
91 | const brandedToken = await BrandedToken.new(
92 | valueToken.address,
93 | 'BT',
94 | 'BrandedToken',
95 | config.decimals,
96 | 35,
97 | 1,
98 | await accountProvider.get(),
99 | );
100 |
101 | const stake = 1;
102 | const mint = await brandedToken.convertToBrandedTokens(stake);
103 | const staker = accountProvider.get();
104 |
105 | await utils.expectRevert(
106 | brandedToken.requestStake(
107 | stake,
108 | mint,
109 | { from: staker },
110 | ),
111 | 'Should revert as valueToken.transferFrom returned false.',
112 | 'ValueToken.transferFrom returned false.',
113 | );
114 | });
115 | });
116 |
117 | contract('Event', async (accounts) => {
118 | const accountProvider = new AccountProvider(accounts);
119 |
120 |
121 | it('Emits StakeRequested event.', async () => {
122 | const {
123 | brandedToken,
124 | } = await brandedTokenUtils.setupBrandedToken(
125 | accountProvider,
126 | );
127 |
128 | const stake = 1;
129 | const mint = await brandedToken.convertToBrandedTokens(stake);
130 | const staker = accountProvider.get();
131 |
132 | const transactionResponse = await brandedToken.requestStake(
133 | stake,
134 | mint,
135 | { from: staker },
136 | );
137 |
138 | const events = Event.decodeTransactionResponse(
139 | transactionResponse,
140 | );
141 |
142 | assert.strictEqual(
143 | events.length,
144 | 1,
145 | );
146 |
147 | Event.assertEqual(events[0], {
148 | name: 'StakeRequested',
149 | args: {
150 | _stakeRequestHash: await brandedToken.stakeRequestHashes(staker),
151 | _staker: staker,
152 | _stake: new BN(stake),
153 | // global nonce is incremented after assignment to a stake request
154 | _nonce: (await brandedToken.nonce()).subn(1),
155 | },
156 | });
157 | });
158 | });
159 |
160 | contract('Storage', async (accounts) => {
161 | const accountProvider = new AccountProvider(accounts);
162 |
163 | it('Successfully stores stake request data', async () => {
164 | const {
165 | brandedToken,
166 | } = await brandedTokenUtils.setupBrandedToken(
167 | accountProvider,
168 | );
169 |
170 | const stake = 1;
171 | const mint = await brandedToken.convertToBrandedTokens(stake);
172 | const staker = accountProvider.get();
173 |
174 | const stakeRequestHash = await brandedToken.requestStake.call(
175 | stake,
176 | mint,
177 | { from: staker },
178 | );
179 |
180 | await brandedToken.requestStake(
181 | stake,
182 | mint,
183 | { from: staker },
184 | );
185 |
186 | assert.strictEqual(
187 | stakeRequestHash,
188 | await brandedToken.stakeRequestHashes(staker),
189 | );
190 |
191 | const stakeRequest = await brandedToken.stakeRequests(stakeRequestHash);
192 |
193 | assert.strictEqual(
194 | stakeRequest.staker,
195 | staker,
196 | );
197 |
198 | assert.strictEqual(
199 | stakeRequest.stake.cmp(
200 | new BN(stake),
201 | ),
202 | 0,
203 | );
204 |
205 | assert.strictEqual(
206 | stakeRequest.nonce.cmp(
207 | // global nonce is incremented after assignment to a stake request
208 | (await brandedToken.nonce()).subn(1),
209 | ),
210 | 0,
211 | );
212 | });
213 |
214 | it('Calculates stakeRequestHash per EIP 712', async () => {
215 | const {
216 | brandedToken,
217 | stakeRequestHash,
218 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
219 | accountProvider,
220 | );
221 |
222 | const BT_STAKE_REQUEST_TYPEHASH = web3.utils.soliditySha3(
223 | 'StakeRequest(address staker,uint256 stake,uint256 nonce)',
224 | );
225 | const stakeRequest = await brandedToken.stakeRequests(stakeRequestHash);
226 | const calculatedHash = web3.utils.soliditySha3(
227 | web3.eth.abi.encodeParameters(
228 | [
229 | 'bytes32',
230 | 'address',
231 | 'uint256',
232 | 'uint256',
233 | ],
234 | [
235 | BT_STAKE_REQUEST_TYPEHASH,
236 | stakeRequest.staker,
237 | stakeRequest.stake.toNumber(),
238 | stakeRequest.nonce.toNumber(),
239 | ],
240 | ),
241 | );
242 |
243 | assert.strictEqual(
244 | calculatedHash,
245 | stakeRequestHash,
246 | );
247 | });
248 | });
249 | });
250 |
--------------------------------------------------------------------------------
/test/branded_token/revoke_stake_request.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 |
22 | const utils = require('../test_lib/utils');
23 | const brandedTokenUtils = require('./utils');
24 |
25 | contract('BrandedToken::revokeStakeRequest', async () => {
26 | contract('Negative Tests', async (accounts) => {
27 | const accountProvider = new AccountProvider(accounts);
28 |
29 | it('Reverts if msg.sender is not staker', async () => {
30 | const {
31 | brandedToken,
32 | stakeRequestHash,
33 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
34 | accountProvider,
35 | );
36 |
37 | const nonStaker = accountProvider.get();
38 |
39 | await utils.expectRevert(
40 | brandedToken.revokeStakeRequest(
41 | stakeRequestHash,
42 | { from: nonStaker },
43 | ),
44 | 'Should revert as msg.sender is not staker.',
45 | 'Msg.sender is not staker.',
46 | );
47 | });
48 |
49 | it('Reverts if valueToken.transfer returns false', async () => {
50 | const {
51 | brandedToken,
52 | staker,
53 | stakeRequestHash,
54 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
55 | accountProvider,
56 | true,
57 | false, // Use EIP20TokenMockPassFail
58 | );
59 |
60 | await utils.expectRevert(
61 | brandedToken.revokeStakeRequest(
62 | stakeRequestHash,
63 | { from: staker },
64 | ),
65 | 'Should revert as valueToken.transfer returned false.',
66 | 'ValueToken.transfer returned false.',
67 | );
68 | });
69 | });
70 |
71 | contract('Event', async (accounts) => {
72 | const accountProvider = new AccountProvider(accounts);
73 |
74 | it('Emits StakeRequestRevoked event', async () => {
75 | const {
76 | brandedToken,
77 | staker,
78 | stake,
79 | stakeRequestHash,
80 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
81 | accountProvider,
82 | );
83 |
84 | const transactionResponse = await brandedToken.revokeStakeRequest(
85 | stakeRequestHash,
86 | { from: staker },
87 | );
88 |
89 | const events = Event.decodeTransactionResponse(
90 | transactionResponse,
91 | );
92 |
93 | assert.strictEqual(
94 | events.length,
95 | 1,
96 | );
97 |
98 | Event.assertEqual(events[0], {
99 | name: 'StakeRequestRevoked',
100 | args: {
101 | _stakeRequestHash: stakeRequestHash,
102 | _staker: staker,
103 | _stake: new BN(stake),
104 | },
105 | });
106 | });
107 | });
108 |
109 | contract('Storage', async (accounts) => {
110 | const accountProvider = new AccountProvider(accounts);
111 |
112 | it('Successfully revokes stake request', async () => {
113 | const {
114 | brandedToken,
115 | staker,
116 | stakeRequestHash,
117 | } = await brandedTokenUtils.setupBrandedTokenAndStakeRequest(
118 | accountProvider,
119 | );
120 |
121 | assert.isOk(
122 | await brandedToken.revokeStakeRequest.call(
123 | stakeRequestHash,
124 | { from: staker },
125 | ),
126 | );
127 |
128 | await brandedToken.revokeStakeRequest(
129 | stakeRequestHash,
130 | { from: staker },
131 | );
132 |
133 | assert.strictEqual(
134 | await brandedToken.stakeRequestHashes(staker),
135 | utils.NULL_BYTES32,
136 | );
137 |
138 | const stakeRequest = await brandedToken.stakeRequests(stakeRequestHash);
139 |
140 | assert.strictEqual(
141 | stakeRequest.staker,
142 | utils.NULL_ADDRESS,
143 | );
144 |
145 | assert.strictEqual(
146 | stakeRequest.stake.cmp(
147 | new BN(0),
148 | ),
149 | 0,
150 | );
151 |
152 | assert.strictEqual(
153 | stakeRequest.nonce.cmp(
154 | new BN(0),
155 | ),
156 | 0,
157 | );
158 | });
159 | });
160 | });
161 |
--------------------------------------------------------------------------------
/test/branded_token/set_name.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const { AccountProvider } = require('../test_lib/utils.js');
19 | const { Event } = require('../test_lib/event_decoder.js');
20 |
21 | const utils = require('../test_lib/utils');
22 | const brandedTokenUtils = require('./utils');
23 |
24 | contract('BrandedToken::setName', async () => {
25 | const newName = 'New BrandedToken';
26 |
27 | contract('Negative Tests', async (accounts) => {
28 | const accountProvider = new AccountProvider(accounts);
29 |
30 | it('Reverts if msg.sender is not a worker', async () => {
31 | const {
32 | brandedToken,
33 | } = await brandedTokenUtils.setupBrandedToken(
34 | accountProvider,
35 | false,
36 | );
37 |
38 | const nonWorker = accountProvider.get();
39 |
40 | await utils.expectRevert(
41 | brandedToken.setName(
42 | newName,
43 | { from: nonWorker },
44 | ),
45 | 'Should revert as msg.sender is not a worker.',
46 | 'Only whitelisted workers are allowed to call this method.',
47 | );
48 | });
49 | });
50 |
51 | contract('Event', async (accounts) => {
52 | const accountProvider = new AccountProvider(accounts);
53 |
54 | it('Emits NameSet event', async () => {
55 | const {
56 | brandedToken,
57 | } = await brandedTokenUtils.setupBrandedToken(
58 | accountProvider,
59 | );
60 |
61 | const worker = accountProvider.get();
62 |
63 | const transactionResponse = await brandedToken.setName(
64 | newName,
65 | { from: worker },
66 | );
67 |
68 | const events = Event.decodeTransactionResponse(
69 | transactionResponse,
70 | );
71 |
72 | assert.strictEqual(
73 | events.length,
74 | 1,
75 | );
76 |
77 | Event.assertEqual(events[0], {
78 | name: 'NameSet',
79 | args: {
80 | _name: newName,
81 | },
82 | });
83 | });
84 | });
85 |
86 | contract('Storage', async (accounts) => {
87 | const accountProvider = new AccountProvider(accounts);
88 |
89 | it('Successfully sets name', async () => {
90 | const {
91 | brandedToken,
92 | } = await brandedTokenUtils.setupBrandedToken(
93 | accountProvider,
94 | );
95 |
96 | const worker = accountProvider.get();
97 |
98 | assert.isOk(
99 | await brandedToken.setName.call(
100 | newName,
101 | { from: worker },
102 | ),
103 | );
104 |
105 | await brandedToken.setName(
106 | newName,
107 | { from: worker },
108 | );
109 |
110 | assert.strictEqual(
111 | newName,
112 | await brandedToken.name(),
113 | );
114 | });
115 | });
116 | });
117 |
--------------------------------------------------------------------------------
/test/branded_token/set_symbol.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const { AccountProvider } = require('../test_lib/utils.js');
19 | const { Event } = require('../test_lib/event_decoder.js');
20 |
21 | const utils = require('../test_lib/utils');
22 | const brandedTokenUtils = require('./utils');
23 |
24 | contract('BrandedToken::setSymbol', async () => {
25 | const newSymbol = 'NBT';
26 |
27 | contract('Negative Tests', async (accounts) => {
28 | const accountProvider = new AccountProvider(accounts);
29 |
30 | it('Reverts if msg.sender is not a worker', async () => {
31 | const {
32 | brandedToken,
33 | } = await brandedTokenUtils.setupBrandedToken(
34 | accountProvider,
35 | false,
36 | );
37 |
38 | const nonWorker = accountProvider.get();
39 |
40 | await utils.expectRevert(
41 | brandedToken.setSymbol(
42 | newSymbol,
43 | { from: nonWorker },
44 | ),
45 | 'Should revert as msg.sender is not a worker.',
46 | 'Only whitelisted workers are allowed to call this method.',
47 | );
48 | });
49 | });
50 |
51 | contract('Event', async (accounts) => {
52 | const accountProvider = new AccountProvider(accounts);
53 |
54 | it('Emits SymbolSet event', async () => {
55 | const {
56 | brandedToken,
57 | } = await brandedTokenUtils.setupBrandedToken(
58 | accountProvider,
59 | );
60 |
61 | const worker = accountProvider.get();
62 |
63 | const transactionResponse = await brandedToken.setSymbol(
64 | newSymbol,
65 | { from: worker },
66 | );
67 |
68 | const events = Event.decodeTransactionResponse(
69 | transactionResponse,
70 | );
71 |
72 | assert.strictEqual(
73 | events.length,
74 | 1,
75 | );
76 |
77 | Event.assertEqual(events[0], {
78 | name: 'SymbolSet',
79 | args: {
80 | _symbol: newSymbol,
81 | },
82 | });
83 | });
84 | });
85 |
86 | contract('Storage', async (accounts) => {
87 | const accountProvider = new AccountProvider(accounts);
88 |
89 | it('Successfully sets symbol', async () => {
90 | const {
91 | brandedToken,
92 | } = await brandedTokenUtils.setupBrandedToken(
93 | accountProvider,
94 | );
95 |
96 | const worker = accountProvider.get();
97 |
98 | assert.isOk(
99 | await brandedToken.setSymbol.call(
100 | newSymbol,
101 | { from: worker },
102 | ),
103 | );
104 |
105 | await brandedToken.setSymbol(
106 | newSymbol,
107 | { from: worker },
108 | );
109 |
110 | assert.strictEqual(
111 | newSymbol,
112 | await brandedToken.symbol(),
113 | );
114 | });
115 | });
116 | });
117 |
--------------------------------------------------------------------------------
/test/branded_token/transfer.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const { AccountProvider } = require('../test_lib/utils.js');
19 |
20 | const utils = require('../test_lib/utils');
21 | const brandedTokenUtils = require('./utils');
22 |
23 | contract('BrandedToken::transfer', async () => {
24 | contract('Negative Tests', async (accounts) => {
25 | const accountProvider = new AccountProvider(accounts);
26 |
27 | it('Reverts if msg.sender is restricted', async () => {
28 | const {
29 | brandedToken,
30 | staker,
31 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
32 | accountProvider,
33 | );
34 |
35 | const to = accountProvider.get();
36 | const brandedTokens = 1;
37 |
38 | await utils.expectRevert(
39 | brandedToken.transfer(
40 | to,
41 | brandedTokens,
42 | { from: staker },
43 | ),
44 | 'Should revert as msg.sender is restricted.',
45 | 'Msg.sender is restricted.',
46 | );
47 | });
48 | });
49 |
50 | contract('Storage', async (accounts) => {
51 | const accountProvider = new AccountProvider(accounts);
52 |
53 | it('Successfully transfers branded tokens', async () => {
54 | const {
55 | brandedToken,
56 | staker,
57 | worker,
58 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
59 | accountProvider,
60 | );
61 |
62 | const to = accountProvider.get();
63 | const brandedTokens = 1;
64 | const restrictionLifted = [staker];
65 |
66 | await brandedToken.liftRestriction(
67 | restrictionLifted,
68 | { from: worker },
69 | );
70 |
71 | assert.isOk(
72 | await brandedToken.transfer.call(
73 | to,
74 | brandedTokens,
75 | { from: staker },
76 | ),
77 | );
78 |
79 | await brandedToken.transfer(
80 | to,
81 | brandedTokens,
82 | { from: staker },
83 | );
84 | });
85 | });
86 | });
87 |
--------------------------------------------------------------------------------
/test/branded_token/transferFrom.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const { AccountProvider } = require('../test_lib/utils.js');
19 |
20 | const utils = require('../test_lib/utils');
21 | const brandedTokenUtils = require('./utils');
22 |
23 | contract('BrandedToken::transferFrom', async () => {
24 | contract('Negative Tests', async (accounts) => {
25 | const accountProvider = new AccountProvider(accounts);
26 |
27 | it('Reverts if msg.sender is restricted', async () => {
28 | const {
29 | brandedToken,
30 | staker,
31 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
32 | accountProvider,
33 | );
34 |
35 | const actor = accountProvider.get();
36 | const to = accountProvider.get();
37 | const brandedTokens = 1;
38 |
39 | await brandedToken.approve(
40 | actor,
41 | brandedTokens,
42 | { from: staker },
43 | );
44 |
45 | await utils.expectRevert(
46 | brandedToken.transferFrom(
47 | staker,
48 | to,
49 | brandedTokens,
50 | { from: actor },
51 | ),
52 | 'Should revert as msg.sender is restricted.',
53 | 'Msg.sender is restricted.',
54 | );
55 | });
56 | });
57 |
58 | contract('Storage', async (accounts) => {
59 | const accountProvider = new AccountProvider(accounts);
60 |
61 | it('Successfully transfers branded tokens', async () => {
62 | const {
63 | brandedToken,
64 | staker,
65 | worker,
66 | } = await brandedTokenUtils.setupBrandedTokenAndAcceptedStakeRequest(
67 | accountProvider,
68 | );
69 |
70 | const actor = accountProvider.get();
71 | const to = accountProvider.get();
72 | const brandedTokens = 1;
73 |
74 | await brandedToken.approve(
75 | actor,
76 | brandedTokens,
77 | { from: staker },
78 | );
79 |
80 | const restrictionLifted = [actor];
81 |
82 | await brandedToken.liftRestriction(
83 | restrictionLifted,
84 | { from: worker },
85 | );
86 |
87 | assert.isOk(
88 | await brandedToken.transferFrom.call(
89 | staker,
90 | to,
91 | brandedTokens,
92 | { from: actor },
93 | ),
94 | );
95 |
96 | await brandedToken.transferFrom(
97 | staker,
98 | to,
99 | brandedTokens,
100 | { from: actor },
101 | );
102 | });
103 | });
104 | });
105 |
--------------------------------------------------------------------------------
/test/branded_token/utils.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OST.com Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const config = require('../test_lib/config');
19 | const web3 = require('../test_lib/web3.js');
20 |
21 | const BrandedToken = artifacts.require('BrandedToken');
22 | const EIP20TokenMockPass = artifacts.require('EIP20TokenMockPass');
23 | const EIP20TokenMockPassFail = artifacts.require('EIP20TokenMockPassFail');
24 | const OrganizationMockPass = artifacts.require('OrganizationMockPass');
25 | const OrganizationMockFail = artifacts.require('OrganizationMockFail');
26 |
27 | /**
28 | * Sets up a BrandedToken.
29 | */
30 | module.exports.setupBrandedToken = async (
31 | accountProvider,
32 | useOrganizationMockPass = true,
33 | useEIP20TokenMockPass = true,
34 | ) => {
35 | const symbol = 'BT';
36 | const name = 'BrandedToken';
37 | const { decimals } = config;
38 | const conversionRate = 35;
39 | const conversionRateDecimals = 1;
40 |
41 | const valueToken = await (
42 | useEIP20TokenMockPass
43 | ? EIP20TokenMockPass.new('VT', 'ValueToken', decimals)
44 | : EIP20TokenMockPassFail.new('VT', 'ValueToken', decimals)
45 | );
46 | const organization = await (
47 | useOrganizationMockPass
48 | ? OrganizationMockPass.new()
49 | : OrganizationMockFail.new()
50 | );
51 |
52 | const brandedToken = await BrandedToken.new(
53 | valueToken.address,
54 | symbol,
55 | name,
56 | decimals,
57 | conversionRate,
58 | conversionRateDecimals,
59 | organization.address,
60 | );
61 |
62 | return {
63 | brandedToken,
64 | };
65 | };
66 |
67 | /**
68 | * Sets up a BrandedToken and a stake request.
69 | */
70 | module.exports.setupBrandedTokenAndStakeRequest = async (
71 | accountProvider,
72 | useOrganizationMockPass = true,
73 | useEIP20TokenMockPass = true,
74 | ) => {
75 | const {
76 | brandedToken,
77 | } = await this.setupBrandedToken(
78 | accountProvider,
79 | useOrganizationMockPass,
80 | useEIP20TokenMockPass,
81 | );
82 |
83 | const staker = accountProvider.get();
84 | const stake = 2;
85 | const mint = await brandedToken.convertToBrandedTokens(stake);
86 |
87 | const stakeRequestHash = await brandedToken.requestStake.call(
88 | stake,
89 | mint,
90 | { from: staker },
91 | );
92 |
93 | await brandedToken.requestStake(
94 | stake,
95 | mint,
96 | { from: staker },
97 | );
98 |
99 | return {
100 | brandedToken,
101 | staker,
102 | stake,
103 | stakeRequestHash,
104 | };
105 | };
106 |
107 | /**
108 | * Sets up a BrandedToken and an accepted stake request.
109 | */
110 | module.exports.setupBrandedTokenAndAcceptedStakeRequest = async (accountProvider) => {
111 | const {
112 | brandedToken,
113 | staker,
114 | stake,
115 | stakeRequestHash,
116 | } = await this.setupBrandedTokenAndStakeRequest(
117 | accountProvider,
118 | );
119 |
120 | const r = web3.utils.soliditySha3('r');
121 | const s = web3.utils.soliditySha3('s');
122 | const v = 0;
123 | const worker = accountProvider.get();
124 |
125 | await brandedToken.acceptStakeRequest(
126 | stakeRequestHash,
127 | r,
128 | s,
129 | v,
130 | { from: worker },
131 | );
132 |
133 | return {
134 | brandedToken,
135 | staker,
136 | stake,
137 | stakeRequestHash,
138 | worker,
139 | };
140 | };
141 |
--------------------------------------------------------------------------------
/test/gateway_composer/approve_token.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const utils = require('../test_lib/utils');
20 | const { AccountProvider } = require('../test_lib/utils.js');
21 |
22 | const gatewayComposerUtils = require('./utils');
23 |
24 | contract('GatewayComposer::approveToken', async (accounts) => {
25 | describe('Negative Tests', async () => {
26 | const accountProvider = new AccountProvider(accounts);
27 |
28 | it('Fails when owner is not the caller.', async () => {
29 | const {
30 | gatewayComposer,
31 | valueToken,
32 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
33 |
34 | const spender = accountProvider.get();
35 | const amount = new BN(10);
36 | await utils.expectRevert(gatewayComposer.approveToken(
37 | valueToken.address,
38 | spender,
39 | amount,
40 | { from: accountProvider.get() },
41 | ),
42 | 'Should revert as msg.sender is not the owner.',
43 | 'Only owner can call the function.');
44 | });
45 |
46 | it('Fails when EIP20 token address is invalid.', async () => {
47 | const {
48 | gatewayComposer,
49 | owner,
50 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
51 |
52 | const to = accountProvider.get();
53 | const amount = new BN(10);
54 | await utils.expectRevert(gatewayComposer.approveToken(
55 | utils.NULL_ADDRESS,
56 | to,
57 | amount,
58 | { from: owner },
59 | ),
60 | 'Should revert as token address is null.',
61 | 'EIP20 token address is zero.');
62 | });
63 | });
64 |
65 | describe('Positive Tests', async () => {
66 | const accountProvider = new AccountProvider(accounts);
67 |
68 | it('Returns true on successful execution.', async () => {
69 | const {
70 | gatewayComposer,
71 | valueToken,
72 | owner,
73 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
74 |
75 | const amount = new BN(10);
76 | // Set GatewayComposer address balance.
77 | await valueToken.setBalance(gatewayComposer.address, amount);
78 | const to = accountProvider.get();
79 | const executionStatus = await gatewayComposer.approveToken.call(
80 | valueToken.address,
81 | to,
82 | amount,
83 | { from: owner },
84 | );
85 | assert.strictEqual(executionStatus, true);
86 | });
87 |
88 | it('Validates destination address allowance after calling approveToken.', async () => {
89 | const {
90 | gatewayComposer,
91 | valueToken,
92 | owner,
93 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
94 |
95 | const amount = new BN(10);
96 | // Set GatewayComposer address balance.
97 | await valueToken.setBalance(gatewayComposer.address, amount);
98 | const to = accountProvider.get();
99 | await gatewayComposer.approveToken(
100 | valueToken.address,
101 | to,
102 | amount,
103 | { from: owner },
104 | );
105 |
106 | const toAllowanceAfter = await valueToken.allowance.call(
107 | gatewayComposer.address,
108 | to,
109 | );
110 | assert.strictEqual(
111 | toAllowanceAfter.cmp(amount),
112 | 0,
113 | );
114 | });
115 | });
116 | });
117 |
--------------------------------------------------------------------------------
/test/gateway_composer/constructor.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const GatewayComposer = artifacts.require('GatewayComposer');
19 |
20 | const utils = require('../test_lib/utils');
21 |
22 | const BrandedToken = artifacts.require('BrandedToken');
23 | const EIP20TokenMock = artifacts.require('EIP20TokenMock');
24 | const { AccountProvider } = require('../test_lib/utils.js');
25 |
26 | /**
27 | * Deploys an EIP20TokenMock contract with the provided decimals.
28 | * @param {number} decimals Decimals for token.
29 | * @return {string} valueToken Address of token.
30 | */
31 | const deployValueToken = async (decimals) => {
32 | const { address: valueToken } = await EIP20TokenMock.new(
33 | 'VT',
34 | 'ValueToken',
35 | decimals,
36 | );
37 |
38 | return valueToken;
39 | };
40 |
41 | contract('GatewayComposer::constructor', async (accounts) => {
42 | describe('Negative Tests', async () => {
43 | let accountProvider;
44 | let deployer;
45 | let owner;
46 | let valueToken;
47 | let brandedToken;
48 |
49 | beforeEach(async () => {
50 | accountProvider = new AccountProvider(accounts);
51 | deployer = accountProvider.get();
52 | owner = accountProvider.get();
53 | valueToken = accountProvider.get();
54 | brandedToken = accountProvider.get();
55 | });
56 |
57 | it('Reverts if owner address is zero.', async () => {
58 | await utils.expectRevert(GatewayComposer.new(
59 | utils.NULL_ADDRESS,
60 | valueToken,
61 | brandedToken,
62 | { from: deployer },
63 | ),
64 | 'It should revert as owner address is zero.',
65 | 'Owner address is zero.');
66 | });
67 |
68 | it('Reverts if ValueToken address is zero.', async () => {
69 | await utils.expectRevert(GatewayComposer.new(
70 | owner,
71 | utils.NULL_ADDRESS,
72 | brandedToken,
73 | { from: deployer },
74 | ),
75 | 'It should revert as ValueToken address is zero.',
76 | 'ValueToken address is zero.');
77 | });
78 |
79 | it('Reverts if branded token address is zero.', async () => {
80 | await utils.expectRevert(GatewayComposer.new(
81 | owner,
82 | valueToken,
83 | utils.NULL_ADDRESS,
84 | { from: deployer },
85 | ),
86 | 'It should revert as BrandedToken address is zero.',
87 | 'BrandedToken address is zero.');
88 | });
89 |
90 | it('Reverts if ValueToken address is same as owner address.', async () => {
91 | await utils.expectRevert(GatewayComposer.new(
92 | valueToken,
93 | valueToken,
94 | brandedToken,
95 | { from: deployer },
96 | ),
97 | 'It should revert as valueToken address is same as owner address.',
98 | 'ValueToken address is same as owner address.');
99 | });
100 |
101 | it('Reverts if BrandedToken address is same as owner address.', async () => {
102 | await utils.expectRevert(GatewayComposer.new(
103 | brandedToken,
104 | valueToken,
105 | brandedToken,
106 | { from: deployer },
107 | ),
108 | 'It should revert as BrandedToken address is same as owner address.',
109 | 'BrandedToken address is same as owner address.');
110 | });
111 |
112 | it('Reverts if ValueToken is not equal to BrandedToken.valueToken.', async () => {
113 | const decimals = 5;
114 |
115 | valueToken = await deployValueToken(decimals);
116 | brandedToken = await BrandedToken.new(
117 | valueToken,
118 | 'TST',
119 | 'Test',
120 | decimals,
121 | 10,
122 | 5,
123 | accountProvider.get(),
124 | { from: deployer },
125 | );
126 | await utils.expectRevert(GatewayComposer.new(
127 | owner,
128 | accountProvider.get(),
129 | brandedToken.address,
130 | { from: deployer },
131 | ),
132 | 'It should revert as ValueToken should match BrandedToken.ValueToken.',
133 | 'ValueToken should match BrandedToken.valueToken.');
134 | });
135 | });
136 |
137 | describe('Storage', async () => {
138 | let accountProvider;
139 | let deployer;
140 | let owner;
141 | let valueToken;
142 | let brandedToken;
143 |
144 | beforeEach(async () => {
145 | accountProvider = new AccountProvider(accounts);
146 | deployer = accountProvider.get();
147 | owner = accountProvider.get();
148 | const decimals = 5;
149 |
150 | valueToken = await deployValueToken(decimals);
151 | brandedToken = await BrandedToken.new(
152 | valueToken,
153 | 'TST',
154 | 'Test',
155 | decimals,
156 | 10,
157 | 5,
158 | accountProvider.get(),
159 | { from: deployer },
160 | );
161 | });
162 |
163 | it('Sets passed arguments correctly.', async () => {
164 | const gatewayComposer = await GatewayComposer.new(
165 | owner,
166 | valueToken,
167 | brandedToken.address,
168 | { from: deployer },
169 | );
170 |
171 | assert.strictEqual(await gatewayComposer.owner.call(), owner);
172 | assert.strictEqual(await gatewayComposer.valueToken.call(), valueToken);
173 | assert.strictEqual(
174 | await gatewayComposer.brandedToken.call(),
175 | brandedToken.address,
176 | );
177 | });
178 | });
179 | });
180 |
--------------------------------------------------------------------------------
/test/gateway_composer/destroy.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 |
20 | const utils = require('../test_lib/utils');
21 | const gatewayComposerUtils = require('./utils');
22 |
23 | const { AccountProvider } = require('../test_lib/utils.js');
24 | const web3 = require('../test_lib/web3.js');
25 |
26 | contract('GatewayComposer::destroy', async (accounts) => {
27 | describe('Negative Tests', async () => {
28 | const accountProvider = new AccountProvider(accounts);
29 |
30 | it('Fails when GatewayComposer ValueToken balance is not zero.', async () => {
31 | const {
32 | valueToken,
33 | gatewayComposer,
34 | owner,
35 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
36 | await valueToken.setBalance(gatewayComposer.address, new BN(10));
37 | await utils.expectRevert(
38 | gatewayComposer.destroy({ from: owner }),
39 | 'It should revert as ValueToken balance is not 0.',
40 | 'ValueToken balance should be 0.',
41 | );
42 | });
43 |
44 | it('Fails when owner is not msg.sender.', async () => {
45 | const {
46 | valueToken,
47 | gatewayComposer,
48 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
49 | await valueToken.setBalance(gatewayComposer.address, new BN(10));
50 | await utils.expectRevert(
51 | gatewayComposer.destroy({ from: accountProvider.get() }),
52 | 'It should revert as only owner can call the function.',
53 | 'Only owner can call the function.',
54 | );
55 | });
56 |
57 | it('Fails when in progress stake requests are present.', async () => {
58 | const {
59 | valueToken,
60 | gatewayComposer,
61 | owner,
62 | brandedToken,
63 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
64 |
65 | const {
66 | stakeAmount,
67 | } = await gatewayComposerUtils.approveGatewayComposer(
68 | valueToken,
69 | gatewayComposer,
70 | owner,
71 | );
72 |
73 | const mintAmount = await brandedToken.convertToBrandedTokens(stakeAmount);
74 | const gateway = accountProvider.get();
75 | const beneficiary = accountProvider.get();
76 | const gasPrice = 1;
77 | const gasLimit = 1;
78 | const nonce = 1;
79 | await gatewayComposer.requestStake(
80 | stakeAmount,
81 | mintAmount,
82 | gateway,
83 | beneficiary,
84 | gasPrice,
85 | gasLimit,
86 | nonce,
87 | { from: owner },
88 | );
89 | await utils.expectRevert(
90 | gatewayComposer.destroy({ from: owner }),
91 | 'It should revert as there are ongoing stake requests.',
92 | 'In progress stake requests are present.',
93 | );
94 | });
95 | });
96 |
97 | describe('Storage', async () => {
98 | let accountProvider;
99 |
100 | beforeEach(async () => {
101 | accountProvider = new AccountProvider(accounts);
102 | });
103 |
104 | it('Removes contract storage & code.', async () => {
105 | const {
106 | gatewayComposer,
107 | owner,
108 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
109 |
110 | await gatewayComposer.destroy({ from: owner });
111 |
112 | const code = await web3.eth.getCode(gatewayComposer.address);
113 | assert.strictEqual(
114 | code,
115 | '0x',
116 | 'Bytecode must be 0x.',
117 | );
118 | });
119 | });
120 | });
121 |
--------------------------------------------------------------------------------
/test/gateway_composer/revert_stake.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const { AccountProvider } = require('../test_lib/utils.js');
20 | const web3 = require('../test_lib/web3.js');
21 |
22 | const gatewayComposerUtils = require('./utils');
23 |
24 | contract('GatewayComposer::revertStake', async (accounts) => {
25 | contract('Negative Tests', async () => {
26 | const accountProvider = new AccountProvider(accounts);
27 |
28 | it('Fails when owner is not the caller', async () => {
29 | const {
30 | gatewayComposer,
31 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
32 |
33 | const {
34 | gateway,
35 | } = await gatewayComposerUtils.setupGatewayPass(
36 | accountProvider,
37 | );
38 |
39 | const penalty = 0;
40 | const messageHash = web3.utils.soliditySha3('hash');
41 |
42 | await utils.expectRevert(
43 | gatewayComposer.revertStake(
44 | gateway.address,
45 | penalty,
46 | messageHash,
47 | { from: accountProvider.get() },
48 | ),
49 | 'Should revert as msg.sender is not the owner.',
50 | 'Only owner can call the function.',
51 | );
52 | });
53 |
54 | it('Fails when gateway address is zero', async () => {
55 | const {
56 | gatewayComposer,
57 | owner,
58 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
59 |
60 | const gateway = utils.NULL_ADDRESS;
61 | const penalty = 0;
62 | const messageHash = web3.utils.soliditySha3('hash');
63 |
64 | await utils.expectRevert(
65 | gatewayComposer.revertStake(
66 | gateway,
67 | penalty,
68 | messageHash,
69 | { from: owner },
70 | ),
71 | 'Should revert as gateway address is zero.',
72 | 'Gateway address is zero.',
73 | );
74 | });
75 |
76 | it('Fails when gateway address is same as owner address', async () => {
77 | const {
78 | gatewayComposer,
79 | owner,
80 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
81 |
82 | const penalty = 0;
83 | const messageHash = web3.utils.soliditySha3('hash');
84 |
85 | await utils.expectRevert(
86 | gatewayComposer.revertStake(
87 | owner,
88 | penalty,
89 | messageHash,
90 | { from: owner },
91 | ),
92 | 'Should revert as gateway address and owner address are same.',
93 | 'Gateway address is same as owner address.',
94 | );
95 | });
96 |
97 | it('Fails if valueToken transferFrom returns false', async () => {
98 | const {
99 | gatewayComposer,
100 | owner,
101 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
102 |
103 | const {
104 | gateway,
105 | } = await gatewayComposerUtils.setupGatewayPass(
106 | accountProvider,
107 | );
108 |
109 | const penalty = 1;
110 | const messageHash = web3.utils.soliditySha3('hash');
111 |
112 | await utils.expectRevert(
113 | gatewayComposer.revertStake(
114 | gateway.address,
115 | penalty,
116 | messageHash,
117 | { from: owner },
118 | ),
119 | 'Should revert as valueToken.transferFrom returned false.',
120 | );
121 | });
122 | });
123 |
124 | contract('Positive Tests', async () => {
125 | const accountProvider = new AccountProvider(accounts);
126 |
127 | it('Returns true on successful execution', async () => {
128 | const {
129 | gatewayComposer,
130 | owner,
131 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
132 |
133 | const {
134 | gateway,
135 | } = await gatewayComposerUtils.setupGatewayPass(
136 | accountProvider,
137 | );
138 |
139 | const penalty = 0;
140 | const messageHash = web3.utils.soliditySha3('hash');
141 |
142 | assert.isOk(
143 | await gatewayComposer.revertStake.call(
144 | gateway.address,
145 | penalty,
146 | messageHash,
147 | { from: owner },
148 | ),
149 | );
150 | });
151 | });
152 | });
153 |
--------------------------------------------------------------------------------
/test/gateway_composer/revoke_stake_request.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const utils = require('../test_lib/utils');
20 | const { AccountProvider } = require('../test_lib/utils.js');
21 | const web3 = require('../test_lib/web3.js');
22 |
23 | const gatewayComposerUtils = require('./utils');
24 |
25 | contract('GatewayComposer::revokeStakeRequest', async (accounts) => {
26 | describe('Negative Tests', async () => {
27 | const accountProvider = new AccountProvider(accounts);
28 |
29 | it('Fails when owner is not the caller.', async () => {
30 | const {
31 | gatewayComposer,
32 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
33 |
34 | const stakeRequestHash = web3.utils.soliditySha3('hash');
35 | await utils.expectRevert(gatewayComposer.revokeStakeRequest(
36 | stakeRequestHash,
37 | { from: accountProvider.get() },
38 | ),
39 | 'Should revert as msg.sender is not the owner.',
40 | 'Only owner can call the function.');
41 | });
42 |
43 | it('Fails when stake request is not found.', async () => {
44 | const {
45 | gatewayComposer,
46 | owner,
47 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
48 |
49 | const invalidStakeRequestHash = web3.utils.soliditySha3('invalid');
50 | await utils.expectRevert(gatewayComposer.revokeStakeRequest(
51 | invalidStakeRequestHash,
52 | { from: owner },
53 | ),
54 | 'Should revert as stake request not found.',
55 | 'Stake request not found.');
56 | });
57 |
58 | it('Fails when BrandedToken.revokeStakeRequest returned false.', async () => {
59 | const {
60 | gatewayComposer,
61 | brandedToken,
62 | valueToken,
63 | owner,
64 | } = await gatewayComposerUtils.setupGatewayComposer(
65 | accountProvider,
66 | false,
67 | );
68 |
69 | const {
70 | stakeAmount,
71 | } = await gatewayComposerUtils.approveGatewayComposer(
72 | valueToken,
73 | gatewayComposer,
74 | owner,
75 | );
76 |
77 | const mintAmount = await brandedToken.convertToBrandedTokens(stakeAmount);
78 | const gateway = accountProvider.get();
79 | const beneficiary = accountProvider.get();
80 | const gasPrice = 1;
81 | const gasLimit = 1;
82 | const nonce = 1;
83 | const stakeRequestHash = await gatewayComposer.requestStake.call(
84 | stakeAmount,
85 | mintAmount,
86 | gateway,
87 | beneficiary,
88 | gasPrice,
89 | gasLimit,
90 | nonce,
91 | { from: owner },
92 | );
93 | await gatewayComposer.requestStake(
94 | stakeAmount,
95 | mintAmount,
96 | gateway,
97 | beneficiary,
98 | gasPrice,
99 | gasLimit,
100 | nonce,
101 | { from: owner },
102 | );
103 |
104 | await utils.expectRevert(gatewayComposer.revokeStakeRequest(
105 | stakeRequestHash,
106 | { from: owner },
107 | ),
108 | 'Should revert as BrandedToken revokeStakeRequest returned false.',
109 | 'BrandedToken revokeStakeRequest returned false.');
110 | });
111 | });
112 |
113 | describe('Positive Tests', async () => {
114 | const accountProvider = new AccountProvider(accounts);
115 |
116 | it('Returns true on successful execution.', async () => {
117 | const {
118 | gatewayComposer,
119 | brandedToken,
120 | valueToken,
121 | owner,
122 | ownerValueTokenBalance,
123 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
124 |
125 | const {
126 | stakeAmount,
127 | } = await gatewayComposerUtils.approveGatewayComposer(
128 | valueToken,
129 | gatewayComposer,
130 | owner,
131 | );
132 |
133 | const mintAmount = await brandedToken.convertToBrandedTokens(stakeAmount);
134 | const gateway = accountProvider.get();
135 | const beneficiary = accountProvider.get();
136 | const gasPrice = 1;
137 | const gasLimit = 1;
138 | const nonce = 1;
139 | const stakeRequestHash = await gatewayComposer.requestStake.call(
140 | stakeAmount,
141 | mintAmount,
142 | gateway,
143 | beneficiary,
144 | gasPrice,
145 | gasLimit,
146 | nonce,
147 | { from: owner },
148 | );
149 | await gatewayComposer.requestStake(
150 | stakeAmount,
151 | mintAmount,
152 | gateway,
153 | beneficiary,
154 | gasPrice,
155 | gasLimit,
156 | nonce,
157 | { from: owner },
158 | );
159 |
160 | const executionStatus = await gatewayComposer.revokeStakeRequest.call(
161 | stakeRequestHash,
162 | { from: owner },
163 | );
164 | assert.strictEqual(executionStatus, true);
165 |
166 | await gatewayComposer.revokeStakeRequest(
167 | stakeRequestHash,
168 | { from: owner },
169 | );
170 |
171 | // stakeRequestHash information is deleted
172 | const stakeRequest = await gatewayComposer.stakeRequests.call(
173 | stakeRequestHash,
174 | );
175 | assert.strictEqual(
176 | (stakeRequest.stakeVT).cmp(new BN(0)),
177 | 0,
178 | );
179 |
180 | // Asserts owner balance.
181 | assert.strictEqual(
182 | (await valueToken.balanceOf.call(owner)).cmp(ownerValueTokenBalance),
183 | 0,
184 | );
185 |
186 | // Sanity check in brandedToken.
187 | // stakeRequestHash information is deleted in BrandedToken.
188 | const btStakeRequest = await brandedToken.stakeRequests.call(
189 | stakeRequestHash,
190 | );
191 | assert.strictEqual(
192 | btStakeRequest.staker,
193 | utils.NULL_ADDRESS,
194 | );
195 | });
196 | });
197 | });
198 |
--------------------------------------------------------------------------------
/test/gateway_composer/transfer_token.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 | const utils = require('../test_lib/utils');
20 | const { AccountProvider } = require('../test_lib/utils.js');
21 |
22 | const gatewayComposerUtils = require('./utils');
23 |
24 | contract('GatewayComposer::transferToken', async (accounts) => {
25 | describe('Negative Tests', async () => {
26 | const accountProvider = new AccountProvider(accounts);
27 |
28 | it('Fails when owner is not the caller.', async () => {
29 | const {
30 | gatewayComposer,
31 | valueToken,
32 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
33 |
34 | const to = accountProvider.get();
35 | const amount = new BN(10);
36 | await utils.expectRevert(gatewayComposer.transferToken(
37 | valueToken.address,
38 | to,
39 | amount,
40 | { from: accountProvider.get() },
41 | ),
42 | 'Should revert as msg.sender is not the owner.',
43 | 'Only owner can call the function.');
44 | });
45 |
46 | it('Fails when EIP20 token address is invalid.', async () => {
47 | const {
48 | gatewayComposer,
49 | owner,
50 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
51 |
52 | const to = accountProvider.get();
53 | const amount = new BN(10);
54 | await utils.expectRevert(gatewayComposer.transferToken(
55 | utils.NULL_ADDRESS,
56 | to,
57 | amount,
58 | { from: owner },
59 | ),
60 | 'Should revert as token address is null.',
61 | 'EIP20 token address is zero.');
62 | });
63 |
64 | it('Fails when ValueToken transfer returned false.', async () => {
65 | const {
66 | gatewayComposer,
67 | valueToken,
68 | owner,
69 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
70 |
71 | // Set GatewayComposer address balance to 0.
72 | await valueToken.setBalance(gatewayComposer.address, new BN(0));
73 |
74 | const to = accountProvider.get();
75 | const amount = new BN(10);
76 | await utils.expectRevert(gatewayComposer.transferToken(
77 | valueToken.address,
78 | to,
79 | amount,
80 | { from: owner },
81 | ),
82 | "Should revert as owner doesn't have sufficient balance.");
83 | });
84 | });
85 |
86 | describe('Positive Tests', async () => {
87 | const accountProvider = new AccountProvider(accounts);
88 |
89 | it('Returns true on successful execution.', async () => {
90 | const {
91 | gatewayComposer,
92 | valueToken,
93 | owner,
94 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
95 |
96 | const amount = new BN(10);
97 | // Set GatewayComposer address balance.
98 | await valueToken.setBalance(gatewayComposer.address, amount);
99 | const to = accountProvider.get();
100 | const executionStatus = await gatewayComposer.transferToken.call(
101 | valueToken.address,
102 | to,
103 | amount,
104 | { from: owner },
105 | );
106 | assert.strictEqual(executionStatus, true);
107 | });
108 |
109 | it('Validates destination address balance after calling transferToken.', async () => {
110 | const {
111 | gatewayComposer,
112 | valueToken,
113 | owner,
114 | } = await gatewayComposerUtils.setupGatewayComposer(accountProvider);
115 |
116 | const amount = new BN(10);
117 | // Set GatewayComposer address balance.
118 | await valueToken.setBalance(gatewayComposer.address, amount);
119 | const to = accountProvider.get();
120 | const toBalanceBefore = await valueToken.balanceOf.call(to);
121 | await gatewayComposer.transferToken(
122 | valueToken.address,
123 | to,
124 | amount,
125 | { from: owner },
126 | );
127 |
128 | const toBalanceAfter = await valueToken.balanceOf.call(to);
129 | assert.strictEqual(
130 | toBalanceAfter.cmp(toBalanceBefore.add(amount)),
131 | 0,
132 | );
133 | });
134 | });
135 | });
136 |
--------------------------------------------------------------------------------
/test/gateway_composer/utils.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OST.com Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 |
20 | const config = require('../test_lib/config');
21 |
22 | const BrandedToken = artifacts.require('BrandedToken');
23 | const MockBrandedTokenFail = artifacts.require('MockBrandedTokenFail');
24 | const GatewayComposer = artifacts.require('GatewayComposer');
25 | const EIP20TokenMock = artifacts.require('EIP20TokenMock');
26 | const MockGatewayPass = artifacts.require('MockGatewayPass');
27 | const MockGatewayFail = artifacts.require('MockGatewayFail');
28 | const MockOrganization = artifacts.require('OrganizationMockPass');
29 |
30 | const symbol = 'Test';
31 | const name = 'Test';
32 | const { decimals } = config;
33 | const conversionRate = 1;
34 | const conversionRateDecimals = 0;
35 |
36 | module.exports.setupGatewayComposer = async (accountProvider, useBTPass = true) => {
37 | const organizationInstance = await MockOrganization.new();
38 | const organization = organizationInstance.address;
39 | const deployer = accountProvider.get();
40 | const owner = accountProvider.get();
41 | const ownerValueTokenBalance = new BN(1000);
42 |
43 | const valueToken = await EIP20TokenMock.new(
44 | symbol,
45 | name,
46 | decimals,
47 | { from: deployer },
48 | );
49 |
50 | await valueToken.setBalance(owner, ownerValueTokenBalance);
51 |
52 | assert.strictEqual(
53 | (await valueToken.balanceOf.call(owner)).cmp(ownerValueTokenBalance),
54 | 0,
55 | );
56 |
57 | let brandedToken;
58 | if (useBTPass === true) {
59 | brandedToken = await this.setupBrandedTokenPass(valueToken, organization);
60 | } else {
61 | brandedToken = await this.setupBrandedTokenFail(valueToken, organization);
62 | }
63 |
64 | const gatewayComposer = await GatewayComposer.new(
65 | owner,
66 | valueToken.address,
67 | brandedToken.address,
68 | );
69 |
70 | return {
71 | valueToken,
72 | brandedToken,
73 | gatewayComposer,
74 | owner,
75 | organization,
76 | ownerValueTokenBalance,
77 | };
78 | };
79 |
80 | module.exports.setupBrandedTokenPass = async (valueToken, organization) => {
81 | const brandedToken = await BrandedToken.new(
82 | valueToken.address,
83 | symbol,
84 | name,
85 | decimals,
86 | conversionRate,
87 | conversionRateDecimals,
88 | organization,
89 | );
90 |
91 | return brandedToken;
92 | };
93 |
94 | module.exports.setupBrandedTokenFail = async (valueToken, organization) => {
95 | const brandedToken = await MockBrandedTokenFail.new(
96 | valueToken.address,
97 | symbol,
98 | name,
99 | decimals,
100 | conversionRate,
101 | conversionRateDecimals,
102 | organization,
103 | );
104 |
105 | return brandedToken;
106 | };
107 |
108 | module.exports.approveGatewayComposer = async (valueToken, gatewayComposer, owner) => {
109 | const stakeAmount = 1;
110 |
111 | await valueToken.approve(
112 | gatewayComposer.address,
113 | stakeAmount,
114 | { from: owner },
115 | );
116 |
117 | return {
118 | stakeAmount,
119 | };
120 | };
121 |
122 | module.exports.setupGatewayPass = async (accountProvider) => {
123 | const mockGatewayPass = await MockGatewayPass.new();
124 |
125 | return {
126 | facilitator: accountProvider.get(),
127 | gateway: mockGatewayPass,
128 | };
129 | };
130 |
131 | module.exports.setupGatewayFail = async (accountProvider) => {
132 | const mockGatewayFail = await MockGatewayFail.new();
133 |
134 | return {
135 | facilitator: accountProvider.get(),
136 | gateway: mockGatewayFail,
137 | };
138 | };
139 |
--------------------------------------------------------------------------------
/test/test_lib/RevertProxy.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.0;
2 |
3 | // Copyright 2018 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | import "truffle/Assert.sol";
18 | import "truffle/DeployedAddresses.sol";
19 |
20 | /**
21 | * @title A proxy contract to catch and test for reverts in other contracts.
22 | *
23 | * @notice Use this contract as a proxy between the test contract and the
24 | * contract under test. It will catch reverts and return false if it
25 | * caught one.
26 | *
27 | * @dev An important caveat here is to recognize the contract caller,
28 | * msg.sender. If you add a proxy in between, then msg.sender will be the
29 | * proxy, which could break authorization and permissioning algorithms. If
30 | * your authorization system allows you to change the owner, you can get
31 | * around this constraint by setting the proxy to be the contract owner.
32 | * It’s also important to know that this only tests throw's at this
33 | * particular level.
34 | * It would be prudent to also ensure there isn’t anything faulty in the
35 | * proxy by creating a second test as a control. This test should be
36 | * called with the appropriate gas and use the proxy to test a function
37 | * where _no_ throw occurs, just to make sure the proxy is setup and
38 | * working as intended.
39 | * Because a throw essentially uses up all gas, one must make doubly sure
40 | * they catch the throw and not a legitimate out-of-gas (OOG) error. As
41 | * well, take care to manage sending Ether through the proxy (for tests
42 | * that require it) as that can be difficult as well.
43 | *
44 | * See also test/core/TestAuxiliaryStake.sol
45 | *
46 | * Usage:
47 | * contract TestThrower {
48 | * function testThrow() {
49 | * Thrower thrower = new Thrower();
50 | * // Set Thrower as the contract to forward requests to the target.
51 | * RevertProxy revertProxy = new RevertProxy(address(thrower));
52 | *
53 | * // Prime the proxy.
54 | * Thrower(address(revertProxy)).doThrow();
55 | * // Execute the call that is supposed to revert.
56 | * // r will be false if it reverted. r will be true if it didn't.
57 | * // Make sure you send enough gas for your contract method.
58 | * bool r = revertProxy.execute.gas(200000)();
59 | *
60 | * Assert.isFalse(r, “Should be false, as it should revert");
61 | * }
62 | * }
63 | *
64 | * Inspired by:
65 | * https://truffleframework.com/tutorials/testing-for-throws-in-solidity-tests.
66 | */
67 | contract RevertProxy {
68 |
69 | /* Public Variables */
70 |
71 | /** target is the address of the contract under test. */
72 | address public target;
73 |
74 | /** data stores the call data that will be sent to the method under test. */
75 | bytes public data;
76 |
77 | /* Constructor */
78 |
79 | /**
80 | * @param _target The address where the executed calls will be sent to.
81 | */
82 | constructor (address _target) public {
83 | target = _target;
84 | }
85 |
86 | /* Public Functions */
87 |
88 | /**
89 | * @notice Updates the target of the proxy so that all subsequent execute
90 | * calls will be made to the new target.
91 | *
92 | * @param _newTarget The address of the contract where to send all execute
93 | * calls to.
94 | */
95 | function updateTarget(address _newTarget) public {
96 | target = _newTarget;
97 | }
98 |
99 | /**
100 | * @notice The fallback function stores the call data so that a call to the
101 | * execute function will use the correct call data.
102 | */
103 | function() external payable {
104 | data = msg.data;
105 | }
106 |
107 | /**
108 | * @notice This will make the call to the target with the call data primed
109 | * in the fallback function.
110 | *
111 | * @return `true` if the call was successful and did not revert, `false` if
112 | * it reverted.
113 | */
114 | function execute() external returns (bool, bytes memory) {
115 | // solium-disable-next-line security/no-low-level-calls
116 | return target.call(data);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/test/test_lib/config.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // ----------------------------------------------------------------------------
16 | //
17 | // http://www.simpletoken.org/
18 | //
19 | // ----------------------------------------------------------------------------
20 |
21 | 'use strict';
22 |
23 | /* eslint-disable @typescript-eslint/no-var-requires */
24 | const { env } = require('process');
25 |
26 | /** Test wide configuration for various tests. */
27 | const config = {
28 | /** Defaults to 18. Can be overriden with the environment variable OPENST_DECIMALS. */
29 | get decimals() {
30 | let decimals = 18;
31 |
32 | if (env.OPENST_DECIMALS) {
33 | decimals = Number.parseInt(env.OPENST_DECIMALS, 10);
34 | }
35 |
36 | return decimals;
37 | },
38 | };
39 |
40 | module.exports = config;
41 |
--------------------------------------------------------------------------------
/test/test_lib/event_decoder.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const web3 = require('../test_lib/web3.js');
19 |
20 | class Event {
21 | static decodeTransactionResponse(transactionResponse) {
22 | const events = [];
23 |
24 | assert.isOk(Object.prototype.hasOwnProperty.call(
25 | transactionResponse, 'logs',
26 | ));
27 |
28 | const { logs } = transactionResponse;
29 |
30 | for (let i = 0; i < logs.length; i += 1) {
31 | events.push({
32 | name: logs[i].event,
33 | args: logs[i].args,
34 | });
35 | }
36 |
37 | return events;
38 | }
39 |
40 | static assertEqual(actual, expected) {
41 | assert.strictEqual(actual.name, expected.name);
42 | Object.keys(expected.args).forEach((key) => {
43 | if (key !== '0' && key !== '1' && key !== '__length__') {
44 | assert.isOk(Object.hasOwnProperty.call(actual.args, key));
45 | if (web3.utils.isBN(expected.args[key])) {
46 | assert.isOk(web3.utils.isBN(actual.args[key]));
47 | assert.isOk(expected.args[key].eq(actual.args[key]));
48 | } else {
49 | assert.strictEqual(actual.args[key], expected.args[key]);
50 | }
51 | }
52 | });
53 |
54 | Object.keys(actual.args).forEach((key) => {
55 | if (Number.isNaN(Number.parseInt(key, 10)) && key !== '__length__') {
56 | assert.isOk(Object.hasOwnProperty.call(expected.args, key));
57 | }
58 | });
59 | }
60 |
61 | static assertEqualMulti(actualList, expectedList) {
62 | assert.strictEqual(
63 | actualList.length,
64 | expectedList.length,
65 | 'Length of actual event list and expected ones should be equal.',
66 | );
67 |
68 | for (let i = 0; i < actualList.lengh; i += 1) {
69 | const actual = actualList[i];
70 | const expected = expectedList[i];
71 | this.assertEqual(actual, expected);
72 | }
73 | }
74 | }
75 |
76 | module.exports = {
77 | Event,
78 | };
79 |
--------------------------------------------------------------------------------
/test/test_lib/utils.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OST.com Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const BN = require('bn.js');
19 |
20 | const assert = require('assert');
21 | const web3 = require('web3');
22 |
23 | const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
24 | const NULL_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
25 | const MAX_UINT256 = new BN(2).pow(new BN(256)).sub(new BN(1));
26 |
27 | module.exports.NULL_ADDRESS = NULL_ADDRESS;
28 | module.exports.NULL_BYTES32 = NULL_BYTES32;
29 | module.exports.MAX_UINT256 = MAX_UINT256;
30 |
31 | module.exports.isNullAddress = address => address === NULL_ADDRESS;
32 |
33 | /**
34 | * Asserts that a call or transaction reverts.
35 | *
36 | * @param {promise} promise The call or transaction.
37 | * @param {string} expectedMessage Optional. If given, the revert message will
38 | * be checked to contain this string.
39 | *
40 | * @throws Will fail an assertion if the call or transaction is not reverted.
41 | */
42 | module.exports.expectRevert = async (
43 | promise, displayMessage, expectedRevertMessage,
44 | ) => {
45 | try {
46 | await promise;
47 | } catch (error) {
48 | assert(
49 | error.message.search('revert') > -1,
50 | `The contract should revert. Instead: ${error.message}`,
51 | );
52 |
53 | if (expectedRevertMessage !== undefined) {
54 | if (error.reason !== undefined) {
55 | assert(
56 | expectedRevertMessage === error.reason,
57 | `\nThe contract should revert with:\n\t"${expectedRevertMessage}" `
58 | + `\ninstead received:\n\t"${error.reason}"\n`,
59 | );
60 | } else {
61 | assert(
62 | error.message.search(expectedRevertMessage) > -1,
63 | `\nThe contract should revert with:\n\t"${expectedRevertMessage}" `
64 | + `\ninstead received:\n\t"${error.message}"\n`,
65 | );
66 | }
67 | }
68 |
69 | return;
70 | }
71 |
72 | assert(false, displayMessage);
73 | };
74 |
75 | module.exports.advanceBlock = async () => {
76 | await web3.currentProvider.send({
77 | jsonrpc: '2.0',
78 | method: 'evm_mine',
79 | id: new Date().getTime(),
80 | }, (err) => {
81 | assert.strictEqual(err, null);
82 | });
83 | };
84 |
85 | /** Receives accounts list and gives away each time one. */
86 | module.exports.AccountProvider = class AccountProvider {
87 | constructor(accounts) {
88 | this.accounts = accounts;
89 | this.index = 0;
90 | }
91 |
92 | get() {
93 | assert(this.index < this.accounts.length);
94 | const account = this.accounts[this.index];
95 | this.index += 1;
96 | return account;
97 | }
98 | };
99 |
--------------------------------------------------------------------------------
/test/test_lib/web3.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const Web3 = require('web3');
19 |
20 | const web3 = new Web3(
21 | new Web3.providers.WebsocketProvider('ws://localhost:8545'),
22 | );
23 |
24 | module.exports = web3;
25 |
--------------------------------------------------------------------------------
/test/utility_branded_token/constructor.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const config = require('../test_lib/config');
19 | const utils = require('../test_lib/utils');
20 |
21 | const UtilityBrandedToken = artifacts.require('UtilityBrandedToken');
22 | const EIP20TokenMock = artifacts.require('EIP20TokenMock');
23 |
24 | contract('UtilityBrandedToken::constructor', async (accounts) => {
25 | let brandedToken;
26 | let organization;
27 | let accountProvider;
28 |
29 | const SYMBOL = 'MOCK';
30 | const NAME = 'Mock Token';
31 | const { decimals: DECIMALS } = config;
32 |
33 | beforeEach(async () => {
34 | accountProvider = new utils.AccountProvider(accounts);
35 | organization = accountProvider.get();
36 | brandedToken = await EIP20TokenMock.new(
37 | SYMBOL,
38 | NAME,
39 | DECIMALS,
40 | { from: organization },
41 | );
42 | });
43 |
44 | describe('Negative Tests', async () => {
45 | it('Reverts if null address is passed as organization', async () => {
46 | await utils.expectRevert(UtilityBrandedToken.new(
47 | brandedToken.address,
48 | SYMBOL,
49 | NAME,
50 | DECIMALS,
51 | utils.NULL_ADDRESS,
52 | { from: organization },
53 | ),
54 | 'Organization contract address should not be zero',
55 | 'Organization contract address must not be zero.');
56 | });
57 | });
58 |
59 | describe('Storage', async () => {
60 | it('Successfully sets state variables', async () => {
61 | const utilityBrandedToken = await UtilityBrandedToken.new(
62 | brandedToken.address,
63 | SYMBOL,
64 | NAME,
65 | DECIMALS,
66 | organization,
67 | { from: organization },
68 | );
69 |
70 | assert.strictEqual(
71 | await utilityBrandedToken.token.call(),
72 | brandedToken.address,
73 | 'Branded token address is incorrect',
74 | );
75 | });
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/test/utility_branded_token/decrease_supply.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const UtilityBrandedTokenUtils = require('./utils');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 | const web3 = require('../test_lib/web3');
22 |
23 | contract('UtilityBrandedToken::decreaseSupply', async (accounts) => {
24 | let testUtilityBrandedToken;
25 | let internalActors;
26 | let tokenHolder1;
27 | let tokenHolder2;
28 | let accountProvider;
29 |
30 | const amount = 10;
31 | const tokenHolder1Balance = 100;
32 | const decreasedAmount = 6;
33 |
34 | beforeEach(async () => {
35 | accountProvider = new utils.AccountProvider(accounts);
36 | tokenHolder1 = accountProvider.get();
37 | tokenHolder2 = accountProvider.get();
38 |
39 | internalActors = [];
40 | internalActors.push(tokenHolder1);
41 | internalActors.push(tokenHolder2);
42 |
43 | ({
44 | testUtilityBrandedToken,
45 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
46 | accountProvider, internalActors,
47 | ));
48 |
49 | await testUtilityBrandedToken.setBalance(tokenHolder1, tokenHolder1Balance);
50 | });
51 |
52 | describe('Storage', async () => {
53 | it('Correctly decreases the supply of tokens', async () => {
54 | const coGateway = tokenHolder2;
55 | await testUtilityBrandedToken.mockSetCoGateway(coGateway);
56 | await testUtilityBrandedToken.increaseSupply(
57 | coGateway,
58 | amount,
59 | { from: tokenHolder2 },
60 | );
61 |
62 | // Before decrease supply.
63 | assert.strictEqual(
64 | (await testUtilityBrandedToken.balanceOf(coGateway)).cmp(
65 | web3.utils.toBN(amount),
66 | ),
67 | 0,
68 | `Balance of coGateway should be ${amount}`,
69 | );
70 | assert.strictEqual(
71 | (await testUtilityBrandedToken.totalSupply()).cmp(
72 | web3.utils.toBN(amount),
73 | ),
74 | 0,
75 | `Total supply should be ${amount}`,
76 | );
77 |
78 | await testUtilityBrandedToken.decreaseSupply(decreasedAmount, { from: coGateway });
79 |
80 | // After decrease supply.
81 | assert.strictEqual(
82 | (await testUtilityBrandedToken.balanceOf(coGateway)).cmp(
83 | web3.utils.toBN(amount - decreasedAmount),
84 | ),
85 | 0,
86 | `Balance of coGateway should be ${amount - decreasedAmount}`,
87 | );
88 | assert.strictEqual(
89 | (await testUtilityBrandedToken.totalSupply()).cmp(
90 | web3.utils.toBN(amount - decreasedAmount),
91 | ),
92 | 0,
93 | `Total supply should be ${amount - decreasedAmount}`,
94 | );
95 | });
96 | });
97 |
98 | describe('Events', async () => {
99 | it('Emits a Transfer event', async () => {
100 | const coGateway = tokenHolder2;
101 | await testUtilityBrandedToken.mockSetCoGateway(coGateway);
102 | await testUtilityBrandedToken.increaseSupply(
103 | coGateway,
104 | amount,
105 | { from: tokenHolder2 },
106 | );
107 |
108 | const transactionResponse = await testUtilityBrandedToken.decreaseSupply(
109 | decreasedAmount,
110 | { from: coGateway },
111 | );
112 |
113 | const events = Event.decodeTransactionResponse(transactionResponse);
114 |
115 | assert.strictEqual(
116 | events.length,
117 | 1,
118 | );
119 |
120 | Event.assertEqual(events[0], {
121 | name: 'Transfer',
122 | args: {
123 | _from: coGateway,
124 | _to: utils.NULL_ADDRESS,
125 | _value: new web3.utils.BN(decreasedAmount),
126 | },
127 | });
128 | });
129 | });
130 | });
131 |
--------------------------------------------------------------------------------
/test/utility_branded_token/exists.js:
--------------------------------------------------------------------------------
1 | // Copyright 2019 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const UtilityBrandedTokenUtils = require('./utils');
20 |
21 | contract('UtilityBrandedToken::exists', async (accounts) => {
22 | let accountProvider;
23 |
24 | beforeEach(async () => {
25 | accountProvider = new utils.AccountProvider(accounts);
26 | });
27 |
28 | describe('Returns', async () => {
29 | it('Returns false if account is not an internal actor', async () => {
30 | const actor = await accountProvider.get();
31 | const {
32 | testUtilityBrandedToken,
33 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
34 | accountProvider,
35 | [actor],
36 | );
37 |
38 | const nonInternalAccount = await accountProvider.get();
39 |
40 | assert.strictEqual(
41 | await testUtilityBrandedToken.exists.call(nonInternalAccount),
42 | false,
43 | 'It should return false for non internal actor',
44 | );
45 | });
46 |
47 | it('Returns true if account is an internal actor', async () => {
48 | const actor = await accountProvider.get();
49 | const {
50 | testUtilityBrandedToken,
51 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
52 | accountProvider,
53 | [actor],
54 | );
55 |
56 | assert.strictEqual(
57 | await testUtilityBrandedToken.exists.call(actor),
58 | true,
59 | 'It should returns for an internal actor',
60 | );
61 | });
62 | });
63 | });
64 |
--------------------------------------------------------------------------------
/test/utility_branded_token/increase_supply.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const UtilityBrandedTokenUtils = require('./utils');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 | const web3 = require('../test_lib/web3');
22 |
23 | contract('UtilityBrandedToken::increaseSupply', async (accounts) => {
24 | let testUtilityBrandedToken;
25 | let internalActors;
26 | let tokenHolder1;
27 | let tokenHolder2;
28 | let tokenHolder3;
29 | let accountProvider;
30 | let coGateway;
31 |
32 | const amount = 10;
33 | const tokenHolder1Balance = 100;
34 |
35 | beforeEach(async () => {
36 | accountProvider = new utils.AccountProvider(accounts);
37 | tokenHolder1 = accountProvider.get();
38 | tokenHolder2 = accountProvider.get();
39 | tokenHolder3 = accountProvider.get();
40 | coGateway = accountProvider.get();
41 |
42 | internalActors = [];
43 | internalActors.push(tokenHolder1);
44 | internalActors.push(tokenHolder3);
45 |
46 | ({
47 | testUtilityBrandedToken,
48 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
49 | accountProvider, internalActors,
50 | ));
51 |
52 | await testUtilityBrandedToken.setBalance(tokenHolder1, tokenHolder1Balance);
53 | await testUtilityBrandedToken.mockSetCoGateway(coGateway);
54 | });
55 |
56 | describe('Negative Tests', async () => {
57 | it('Reverts if beneficiary address is not registered internal actor', async () => {
58 | await utils.expectRevert(
59 | testUtilityBrandedToken.increaseSupply(
60 | tokenHolder2,
61 | amount,
62 | { from: coGateway },
63 | ),
64 | 'Beneficiary should be registered internal actor',
65 | 'Beneficiary is not an internal actor.',
66 | );
67 | });
68 | });
69 |
70 | describe('Storage', async () => {
71 | it('Correctly increases the supply of tokens', async () => {
72 | // Before increase in supply
73 | assert.strictEqual(
74 | (await testUtilityBrandedToken.balanceOf(tokenHolder3)).cmp(
75 | web3.utils.toBN(0),
76 | ),
77 | 0,
78 | 'Balance of tokeholder3 should be zero',
79 | );
80 | assert.strictEqual(
81 | (await testUtilityBrandedToken.totalSupply()).cmp(
82 | web3.utils.toBN(0),
83 | ),
84 | 0,
85 | 'Total supply should be zero',
86 | );
87 |
88 | await testUtilityBrandedToken.increaseSupply(
89 | tokenHolder3,
90 | amount,
91 | { from: coGateway },
92 | );
93 |
94 | // After increase supply.
95 | assert.strictEqual(
96 | (await testUtilityBrandedToken.totalSupply()).cmp(
97 | web3.utils.toBN(amount),
98 | ),
99 | 0,
100 | `Total supply should be ${amount}`,
101 | );
102 | assert.strictEqual(
103 | (await testUtilityBrandedToken.balanceOf(tokenHolder3)).cmp(
104 | web3.utils.toBN(amount),
105 | ),
106 | 0,
107 | `Total supply should be ${amount}`,
108 | );
109 | });
110 | });
111 |
112 | describe('Events', async () => {
113 | it('Emits a Transfer event', async () => {
114 | const transactionResponse = await testUtilityBrandedToken.increaseSupply(
115 | tokenHolder3,
116 | amount,
117 | { from: coGateway },
118 | );
119 |
120 | const events = Event.decodeTransactionResponse(transactionResponse);
121 |
122 | assert.strictEqual(
123 | events.length,
124 | 1,
125 | );
126 |
127 | Event.assertEqual(events[0], {
128 | name: 'Transfer',
129 | args: {
130 | _from: utils.NULL_ADDRESS,
131 | _to: tokenHolder3,
132 | _value: new web3.utils.BN(amount),
133 | },
134 | });
135 | });
136 | });
137 | });
138 |
--------------------------------------------------------------------------------
/test/utility_branded_token/register_internal_actors.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const { Event } = require('../test_lib/event_decoder');
20 | const UtilityBrandedTokenUtils = require('./utils');
21 |
22 | contract('Internal::registerInternalActors', async (accounts) => {
23 | let organization;
24 | let accountProvider;
25 | let worker;
26 | let testUtilityBrandedToken;
27 |
28 | beforeEach(async () => {
29 | accountProvider = new utils.AccountProvider(accounts);
30 |
31 | ({
32 | testUtilityBrandedToken,
33 | organization,
34 | worker,
35 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
36 | accountProvider, [],
37 | ));
38 | });
39 |
40 | describe('Negative Tests', async () => {
41 | it('Reverts if non-worker address is adding internal actor', async () => {
42 | const internalActors = [];
43 | internalActors.push(accountProvider.get());
44 | const nonWorker = accountProvider.get();
45 |
46 | await utils.expectRevert(testUtilityBrandedToken.registerInternalActors(
47 | internalActors,
48 | { from: nonWorker },
49 | ),
50 | 'Worker should be registered.',
51 | 'Only whitelisted workers are allowed to call this method.');
52 | });
53 | });
54 |
55 | describe('Events', async () => {
56 | it('Emits InternalActorRegistered events for multiple internal actors registration', async () => {
57 | const internalActors = [];
58 | internalActors.push(accountProvider.get());
59 | internalActors.push(accountProvider.get());
60 | internalActors.push(accountProvider.get());
61 |
62 | const transactionResponse = await testUtilityBrandedToken.registerInternalActors(
63 | internalActors,
64 | { from: worker },
65 | );
66 |
67 | const events = Event.decodeTransactionResponse(
68 | transactionResponse,
69 | );
70 |
71 | Event.assertEqualMulti(events, [{
72 | name: 'InternalActorRegistered',
73 | args:
74 | {
75 | _organization: organization,
76 | _actor: internalActors[0],
77 | },
78 | },
79 | {
80 | name: 'InternalActorRegistered',
81 | args:
82 | {
83 | _organization: organization,
84 | _actor: internalActors[1],
85 | },
86 | },
87 | {
88 | name: 'InternalActorRegistered',
89 | args:
90 | {
91 | _organization: organization,
92 | _actor: internalActors[2],
93 | },
94 | },
95 | ]);
96 | });
97 |
98 | it('Doesn\'t register already registered internal actor', async () => {
99 | const internalActors = [];
100 | internalActors.push(accountProvider.get());
101 |
102 | await testUtilityBrandedToken.registerInternalActors(
103 | internalActors,
104 | { from: worker },
105 | );
106 |
107 | const transactionResponse = await testUtilityBrandedToken.registerInternalActors(
108 | internalActors,
109 | { from: worker },
110 | );
111 |
112 | const events = Event.decodeTransactionResponse(
113 | transactionResponse,
114 | );
115 |
116 | assert.strictEqual(
117 | events.length,
118 | 0,
119 | 'Should not emit InternalActorRegistered event',
120 | );
121 | });
122 | });
123 |
124 | describe('Storage', async () => {
125 | it('Successfully registers internal actors', async () => {
126 | const internalActors = [];
127 | internalActors.push(accountProvider.get());
128 | internalActors.push(accountProvider.get());
129 |
130 | await testUtilityBrandedToken.registerInternalActors(
131 | internalActors,
132 | { from: worker },
133 | );
134 |
135 | assert.strictEqual(
136 | await testUtilityBrandedToken.isInternalActor.call(internalActors[0]),
137 | true,
138 | );
139 | assert.strictEqual(
140 | await testUtilityBrandedToken.isInternalActor.call(internalActors[1]),
141 | true,
142 | );
143 | });
144 | });
145 | });
146 |
--------------------------------------------------------------------------------
/test/utility_branded_token/set_cogateway.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const UtilityBrandedTokenUtils = require('./utils');
20 | const { Event } = require('../test_lib/event_decoder.js');
21 |
22 | const MockCoGateway = artifacts.require('MockCoGateway');
23 |
24 | contract('UtilityBrandedToken::setCoGateway', async (accounts) => {
25 | let internalActor;
26 | let tokenHolder1;
27 | let tokenHolder3;
28 | let accountProvider;
29 | let mockCoGateway;
30 | let testUtilityBrandedToken;
31 | let testUtilityBrandedToken2;
32 | let organization;
33 |
34 | const tokenHolder1Balance = 100;
35 |
36 | beforeEach(async () => {
37 | accountProvider = new utils.AccountProvider(accounts);
38 | tokenHolder1 = accountProvider.get();
39 | tokenHolder3 = accountProvider.get();
40 |
41 | internalActor = [];
42 | internalActor.push(tokenHolder1);
43 | internalActor.push(tokenHolder3);
44 |
45 | ({
46 | testUtilityBrandedToken,
47 | organization,
48 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
49 | accountProvider, internalActor,
50 | ));
51 |
52 | mockCoGateway = await MockCoGateway.new(
53 | testUtilityBrandedToken.address,
54 | );
55 |
56 | await testUtilityBrandedToken.setBalance(tokenHolder1, tokenHolder1Balance);
57 | });
58 |
59 | describe('Negative Tests', async () => {
60 | it('Reverts if non-owner address sets the coGateway', async () => {
61 | const nonOrganization = accountProvider.get();
62 | await utils.expectRevert(testUtilityBrandedToken.setCoGateway(
63 | mockCoGateway.address,
64 | { from: nonOrganization },
65 | ),
66 | 'Only organization or admin can call',
67 | 'Only the organization is allowed to call this method.');
68 | });
69 |
70 | it('Reverts if coGateway address is zero', async () => {
71 | await utils.expectRevert(testUtilityBrandedToken.setCoGateway(
72 | utils.NULL_ADDRESS,
73 | { from: organization },
74 | ),
75 | 'Only organization or admin can call',
76 | 'CoGateway address should not be zero.');
77 | });
78 |
79 | it('Reverts if coGateway address is already set', async () => {
80 | await testUtilityBrandedToken.setCoGateway(
81 | mockCoGateway.address,
82 | { from: organization },
83 | );
84 |
85 | const mockCoGateway2 = await MockCoGateway.new(
86 | testUtilityBrandedToken.address,
87 | );
88 |
89 | await utils.expectRevert(testUtilityBrandedToken.setCoGateway(
90 | mockCoGateway2.address,
91 | { from: organization },
92 | ),
93 | 'CoGateway address cannot be set again.',
94 | 'CoGateway address is already set.');
95 | });
96 |
97 | it('Reverts if CoGateway is linked to other utility token', async () => {
98 | const utilityMock = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
99 | accountProvider, internalActor,
100 | );
101 |
102 | testUtilityBrandedToken2 = utilityMock.testUtilityBrandedToken;
103 |
104 | const mockCoGateway2 = await MockCoGateway.new(
105 | testUtilityBrandedToken2.address,
106 | );
107 |
108 | await utils.expectRevert(testUtilityBrandedToken.setCoGateway(
109 | mockCoGateway2.address,
110 | { from: organization },
111 | ),
112 | 'CoGateway is linked to other utility token',
113 | 'CoGateway should be linked with this utility token.');
114 | });
115 | });
116 |
117 | describe('Storage', async () => {
118 | it('Successfully sets the coGateway address', async () => {
119 | await testUtilityBrandedToken.setCoGateway(
120 | mockCoGateway.address,
121 | { from: organization },
122 | );
123 |
124 | assert.strictEqual(
125 | await testUtilityBrandedToken.coGateway.call(),
126 | mockCoGateway.address,
127 | 'CoGateway address is incorrect',
128 | );
129 | });
130 |
131 | it('Checks that coGateway is set as an internal actor.', async () => {
132 | await testUtilityBrandedToken.setCoGateway(
133 | mockCoGateway.address,
134 | { from: organization },
135 | );
136 |
137 | assert.isOk(
138 | await testUtilityBrandedToken.isInternalActor.call(mockCoGateway.address),
139 | );
140 | });
141 | });
142 |
143 | describe('Events', async () => {
144 | it('Emits a CoGatewaySet event', async () => {
145 | const transactionResponse = await testUtilityBrandedToken.setCoGateway(
146 | mockCoGateway.address,
147 | { from: organization },
148 | );
149 |
150 | const events = Event.decodeTransactionResponse(transactionResponse);
151 |
152 | assert.strictEqual(
153 | events.length,
154 | 1,
155 | 'Only one event should be raised',
156 | );
157 |
158 | Event.assertEqual(events[0], {
159 | name: 'CoGatewaySet',
160 | args: {
161 | _coGateway: mockCoGateway.address,
162 | },
163 | });
164 | });
165 | });
166 | });
167 |
--------------------------------------------------------------------------------
/test/utility_branded_token/transfer.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const UtilityBrandedTokenUtils = require('./utils');
20 | const web3 = require('../test_lib/web3');
21 |
22 | contract('UtilityBrandedToken::transfer', async (accounts) => {
23 | let testUtilityBrandedToken;
24 | let internalActors;
25 | let tokenHolder1;
26 | let tokenHolder2;
27 | let worker;
28 | let accountProvider;
29 |
30 | const amount = 10;
31 | const tokenHolder1Balance = 100;
32 |
33 | beforeEach(async () => {
34 | accountProvider = new utils.AccountProvider(accounts);
35 | tokenHolder1 = accountProvider.get();
36 | tokenHolder2 = accountProvider.get();
37 |
38 | internalActors = [];
39 | internalActors.push(tokenHolder1);
40 |
41 | ({
42 | testUtilityBrandedToken,
43 | worker,
44 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
45 | accountProvider, internalActors,
46 | ));
47 |
48 | await testUtilityBrandedToken.setBalance(tokenHolder1, tokenHolder1Balance);
49 | });
50 |
51 | describe('Negative Tests', async () => {
52 | it('Reverts if to address is not registered internal actor', async () => {
53 | await utils.expectRevert(testUtilityBrandedToken.transfer(
54 | tokenHolder2,
55 | amount,
56 | { from: tokenHolder1 },
57 | ),
58 | 'To address should be registered internal actor',
59 | 'To address is not an internal actor.');
60 | });
61 | });
62 |
63 | describe('Storage', async () => {
64 | it('Successfully transfers to internal actor', async () => {
65 | internalActors.push(tokenHolder2);
66 |
67 | await testUtilityBrandedToken.registerInternalActors(
68 | internalActors,
69 | { from: worker },
70 | );
71 |
72 | assert.strictEqual(
73 | (await testUtilityBrandedToken.balanceOf(tokenHolder2)).cmp(
74 | web3.utils.toBN(0),
75 | ),
76 | 0,
77 | 'Tokenholder2 balance should be zero',
78 | );
79 |
80 | await testUtilityBrandedToken.transfer(
81 | tokenHolder2,
82 | amount,
83 | { from: tokenHolder1 },
84 | );
85 |
86 | assert.strictEqual(
87 | (await testUtilityBrandedToken.balanceOf(tokenHolder2)).cmp(
88 | web3.utils.toBN(amount),
89 | ),
90 | 0,
91 | `Balance of tokenholder2 should be ${amount}`,
92 | );
93 | });
94 | });
95 | });
96 |
--------------------------------------------------------------------------------
/test/utility_branded_token/transfer_from.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OpenST Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const utils = require('../test_lib/utils');
19 | const UtilityBrandedTokenUtils = require('./utils');
20 | const web3 = require('../test_lib/web3');
21 |
22 | contract('UtilityBrandedToken::transferFrom', async (accounts) => {
23 | let testUtilityBrandedToken;
24 | let internalActors;
25 | let tokenHolder1;
26 | let tokenHolder2;
27 | let tokenHolder3;
28 | let worker;
29 | let accountProvider;
30 |
31 | const approvalAmount = 50;
32 | const amount = 10;
33 | const tokenHolder1Balance = 100;
34 |
35 | beforeEach(async () => {
36 | accountProvider = new utils.AccountProvider(accounts);
37 | tokenHolder1 = accountProvider.get();
38 | tokenHolder2 = accountProvider.get();
39 | tokenHolder3 = accountProvider.get();
40 | worker = accountProvider.get();
41 |
42 | internalActors = [];
43 | internalActors.push(tokenHolder1);
44 | internalActors.push(tokenHolder3);
45 |
46 | ({
47 | testUtilityBrandedToken,
48 | worker,
49 | } = await UtilityBrandedTokenUtils.setupUtilityBrandedToken(
50 | accountProvider, internalActors,
51 | ));
52 |
53 | await testUtilityBrandedToken.registerInternalActors(
54 | internalActors,
55 | { from: worker },
56 | );
57 |
58 | await testUtilityBrandedToken.setBalance(tokenHolder1, tokenHolder1Balance);
59 |
60 | await testUtilityBrandedToken.approve(
61 | tokenHolder3,
62 | approvalAmount,
63 | { from: tokenHolder1 },
64 | );
65 | });
66 |
67 | describe('Negative Tests', async () => {
68 | it('Reverts if to address is not registered internal actor', async () => {
69 | await utils.expectRevert(testUtilityBrandedToken.transferFrom(
70 | tokenHolder1,
71 | tokenHolder2,
72 | amount,
73 | { from: tokenHolder3 },
74 | ),
75 | 'To address should be registered internal actor',
76 | 'To address is not an internal actor.');
77 | });
78 | });
79 |
80 | describe('Storage', async () => {
81 | it('Successfully transfers to internal actor', async () => {
82 | internalActors.push(tokenHolder2);
83 | await testUtilityBrandedToken.registerInternalActors(
84 | internalActors,
85 | { from: worker },
86 | );
87 | assert.strictEqual(
88 | (await testUtilityBrandedToken.balanceOf(tokenHolder2)).cmp(
89 | web3.utils.toBN(0),
90 | ),
91 | 0,
92 | 'Balance of tokenholder2 should be zero',
93 | );
94 |
95 | await testUtilityBrandedToken.transferFrom(
96 | tokenHolder1,
97 | tokenHolder2,
98 | amount,
99 | { from: tokenHolder3 },
100 | );
101 |
102 | assert.strictEqual(
103 | (await testUtilityBrandedToken.balanceOf(tokenHolder2)).cmp(
104 | web3.utils.toBN(amount),
105 | ),
106 | 0,
107 | `Balance of tokenholder should be ${amount}`,
108 | );
109 | });
110 | });
111 | });
112 |
--------------------------------------------------------------------------------
/test/utility_branded_token/utils.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 OST.com Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | 'use strict';
17 |
18 | const config = require('../test_lib/config');
19 |
20 | const TestUtilityBrandedToken = artifacts.require('TestUtilityBrandedToken');
21 | const EIP20TokenMock = artifacts.require('EIP20TokenMock');
22 | const MockOrganization = artifacts.require('MockOrganization');
23 |
24 | /**
25 | * Setup UtilityBrandedToken.
26 | */
27 | module.exports.setupUtilityBrandedToken = async (accountProvider, internalActor) => {
28 | const SYMBOL = 'MOCK';
29 | const NAME = 'Mock Token';
30 | const { decimals: DECIMALS } = config;
31 |
32 | const {
33 | mockOrganization,
34 | worker,
35 | organization,
36 | } = await this.setupOrganization(accountProvider);
37 |
38 | const brandedToken = await EIP20TokenMock.new(
39 | SYMBOL,
40 | NAME,
41 | DECIMALS,
42 | { from: organization },
43 | );
44 |
45 | const testUtilityBrandedToken = await TestUtilityBrandedToken.new(
46 | brandedToken.address,
47 | SYMBOL,
48 | NAME,
49 | DECIMALS,
50 | mockOrganization.address,
51 | { from: organization },
52 | );
53 |
54 | await testUtilityBrandedToken.registerInternalActors(
55 | internalActor,
56 | { from: worker },
57 | );
58 |
59 | return {
60 | testUtilityBrandedToken, worker, organization,
61 | };
62 | };
63 |
64 | /**
65 | * Creates an instance of MockOrganization contract and sets worker.
66 | */
67 | module.exports.setupOrganization = async (accountProvider) => {
68 | const worker = accountProvider.get();
69 | const organization = accountProvider.get();
70 |
71 | const mockOrganization = await MockOrganization.new(
72 | organization,
73 | worker,
74 | );
75 |
76 | return {
77 | mockOrganization, worker, organization,
78 | };
79 | };
80 |
--------------------------------------------------------------------------------
/tools/build_package.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // Copyright 2019 OpenST Ltd.
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 | //
17 | // ----------------------------------------------------------------------------
18 | //
19 | // http://www.simpletoken.org/
20 | //
21 | // ----------------------------------------------------------------------------
22 |
23 | /**
24 | * @file This file runs as part of the npm packaging process.
25 | *
26 | * It reads a set number of contracts from the truffle build directory and
27 | * extracts ABI and BIN of each contract. The extracted information is added to
28 | * a new object that is finally serialized to disk. That JSON file will be
29 | * exported by this package.
30 | *
31 | * To add a contract to the published package, add its name to array of contract
32 | * names.
33 | */
34 |
35 | const fs = require('fs');
36 | const path = require('path');
37 |
38 | const contractNames = [
39 | 'BrandedToken',
40 | 'CoGatewayUtilityTokenInterface',
41 | 'EIP20Interface',
42 | 'EIP20Token',
43 | 'GatewayComposer',
44 | 'GatewayInterface',
45 | 'OrganizationInterface',
46 | 'Organized',
47 | 'UtilityBrandedToken',
48 | 'UtilityTokenInterface',
49 | ];
50 |
51 | const contracts = {};
52 |
53 | contractNames.forEach((contract) => {
54 | const contractPath = path.join(
55 | __dirname,
56 | `../build/contracts/${contract}.json`,
57 | );
58 |
59 | if (!fs.existsSync(contractPath)) {
60 | throw new Error(
61 | `Cannot read file ${contractPath}.`
62 | + 'Truffle compile must be run before building the package.'
63 | + 'That should be done automatically when running `npm publish`.',
64 | );
65 | }
66 |
67 | const contractFile = fs.readFileSync(contractPath);
68 | const metaData = JSON.parse(contractFile);
69 |
70 | contracts[contract] = {};
71 | contracts[contract].abi = metaData.abi;
72 |
73 | if (metaData.bytecode !== '0x') {
74 | contracts[contract].bin = metaData.bytecode;
75 | }
76 | });
77 |
78 | fs.writeFileSync('dist/contracts.json', JSON.stringify(contracts));
79 |
--------------------------------------------------------------------------------
/tools/compile.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | CONTRACTDIR=./contracts/*.sol
4 | ABIDIRUTILITY=./contracts/abi
5 | BINDIRVALUE=./contracts/bin
6 |
7 | mkdir -p "$ABIDIRUTILITY"
8 | mkdir -p "$BINDIRVALUE"
9 |
10 | for filename in $CONTRACTDIR; do
11 | echo ""
12 | echo "Compiling ${filename}"
13 | echo ""
14 | solc --abi --optimize --optimize-runs 200 --overwrite ${filename} -o $ABIDIRUTILITY
15 | solc --bin --optimize --optimize-runs 200 --overwrite ${filename} -o $BINDIRVALUE
16 | done
--------------------------------------------------------------------------------
/tools/runGanacheCli.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | node_modules/.bin/ganache-cli \
3 | --accounts=100 \
4 | --defaultBalanceEther=100 \
5 | --gasLimit 0xfffffffffff
6 |
--------------------------------------------------------------------------------
/tools/test_range.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2019 OpenST Ltd.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # ----------------------------------------------------------------------------
18 | #
19 | # http://www.simpletoken.org/
20 | #
21 | # ----------------------------------------------------------------------------
22 |
23 | ###
24 | # Runs tests sequentially for a range of decimal values.
25 | #
26 | # Example run with decimals 12 - 18 (inclusive):
27 | #
28 | # ```bash
29 | # npm run test:range -- 12 18
30 | # ```
31 | #
32 | # You can provide only one argument and the tests will run for that specific
33 | # decimal.
34 | ###
35 |
36 | # Tracking the exit code to run further tests if they fail for a spcefic decimal.
37 | EXIT_CODE=0
38 |
39 | # Tracking failed decimals for error output.
40 | FAILED_DECIMALS=""
41 |
42 | function handle_error {
43 | # On first iteration, no extra comma
44 | if [ $EXIT_CODE -eq 0 ];
45 | then
46 | FAILED_DECIMALS="$1"
47 | else
48 | FAILED_DECIMALS="${FAILED_DECIMALS}, $1"
49 | fi
50 | EXIT_CODE=1
51 | }
52 |
53 | function handle_exit {
54 | if [ $EXIT_CODE -ne 0 ];
55 | then
56 | echo ""
57 | echo "### Errors for the following decimals:"
58 | echo "${FAILED_DECIMALS}"
59 | echo ""
60 | else
61 | echo ""
62 | echo "### Done"
63 | echo ""
64 | fi
65 |
66 | exit $EXIT_CODE
67 | }
68 |
69 | echo ""
70 |
71 | if [ $# -ne 1 ] && [ $# -ne 2 ];
72 | then
73 | echo "Wrong number of parameters given."
74 | echo "Run with two arguments: start and end of range inclusive."
75 | echo "Example:"
76 | echo "npm run test:range -- 16 20"
77 | echo ""
78 | echo "If you provide only one argument, the tests will be run for that value."
79 | echo ""
80 | exit 1
81 | fi
82 |
83 | # Start and end values should be provided on the command line.
84 | START=$1
85 |
86 | if [ $# -eq 1 ];
87 | then
88 | END=$START
89 | else
90 | END=$2
91 | fi
92 |
93 | for DECIMALS in $(seq "${START}" "${END}");
94 | do
95 | echo "### Running tests with ${DECIMALS} decimals."
96 | export OPENST_DECIMALS=$DECIMALS
97 | npm test || handle_error $DECIMALS
98 | done
99 |
100 | handle_exit
101 |
--------------------------------------------------------------------------------
/truffle.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | networks: {
3 | development: {
4 | host: 'localhost',
5 | network_id: '*',
6 | port: 8545,
7 | gas: 12000000,
8 | gasPrice: 0x01,
9 | },
10 | },
11 | coverage: {
12 | host: 'localhost',
13 | network_id: '*',
14 | port: 8555, // <-- If you change this, also set the port option in .solcover.js.
15 | gas: 0xfffffffffff, // <-- Use this high gas value
16 | gasPrice: 0x01, // <-- Use this low gas price
17 | },
18 | solc: {
19 | optimizer: {
20 | enabled: true,
21 | // set to same number of runs as openst-platform
22 | // so that integration tests
23 | // give accurate gas measurements
24 | runs: 200,
25 | },
26 | },
27 | };
28 |
--------------------------------------------------------------------------------