Compare commits

...

50 Commits

Author SHA1 Message Date
0f872c8f1e
7.5.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-01-20 15:39:11 -05:00
484a9ffcaf Merge pull request 'Add amountSats to expense items' (#249) from chore/update_schemas into master
Reviewed-on: #249
2025-01-20 20:35:11 +00:00
6e9f565587
Add more logs for IPFS failures
All checks were successful
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2025-01-20 15:32:50 -05:00
f4634fe692
Add amountSats to expense items
closes #248
2025-01-20 15:31:19 -05:00
68968e1fbd
Update Kosmos schemas 2025-01-20 14:41:41 -05:00
Râu Cao
a2ebc609ea
7.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-29 15:03:03 +02:00
beca6afc4f Merge pull request 'Add npm version/release script' (#247) from dev/versioning into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #247
2023-08-29 12:59:56 +00:00
Râu Cao
90223dd22e
Add npm version script
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 2s
closes #46
2023-08-29 14:57:07 +02:00
ea3a591a0c Merge pull request 'Improve data in development seeds/bootstrap' (#246) from dev/improve_seeds into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #246
2023-08-29 10:19:26 +00:00
Râu Cao
e0f20d363c
Pre-confirm some contributions and reimbursements on bootstrap
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-08-24 16:43:52 +02:00
Râu Cao
5e33381f2a
Allow overriding confirmedAtBlock and vetoed in JS API 2023-08-24 16:43:18 +02:00
1f91a13f06 Merge pull request 'Update reimbursement to support migration' (#244) from feature/reimbursement_migrations into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #244
2023-08-24 14:04:22 +00:00
7d2a492fc9
Update reimbursement to support migration
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-08-24 15:45:28 +02:00
Râu Cao
30490ce393
"Fix" default network name in hardhat config
All checks were successful
continuous-integration/drone/push Build is passing
Some scripts require "hardhat" while others require "localhost". But we
can fix whatever doesn't work directly in the package config.
2023-08-24 14:52:38 +02:00
Râu Cao
f0a71ca8f1
7.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-13 21:01:34 +02:00
Râu Cao
117918e66f
Remove obsolete npm scripts 2023-08-13 20:59:09 +02:00
d0d456b357 Merge pull request 'Migrate to proper RSK testnet deployment' (#242) from new-final-deploy into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #242
2023-08-13 18:54:35 +00:00
cda84fa2ce Add support to start the contribution import from a specific id
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-08-13 14:46:48 +02:00
97e2db93be Add reimbursement import 2023-08-13 14:46:48 +02:00
17c582f6df Add export script for reimbursements 2023-08-13 14:46:48 +02:00
Râu Cao
914d4d9585
Update hardhat config
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-08-07 23:06:40 +02:00
Râu Cao
0deeba14fc
Upgrade testnet contribution contract, reinit contributor contract 2023-08-07 23:05:38 +02:00
Râu Cao
c61632d949
Resolve some solhint errors and warnings 2023-08-07 23:05:15 +02:00
Râu Cao
0b593ec795
Merge branch 'master' into new-final-deploy 2023-08-07 22:07:45 +02:00
Râu Cao
401c528e95
Ignore .env 2023-08-07 22:06:42 +02:00
ed2033980c deploy to RSK testnet
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-07 21:55:08 +02:00
17c7a36cb4 Add openzeppelin to repo
but ignore local development chain
2023-08-07 21:10:03 +02:00
Râu Cao
1cb777aa44
Add missing import
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-27 12:00:17 +02:00
Râu Cao
21522a86a0
7.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-27 11:37:22 +02:00
Râu Cao
269a2cf87a
Update JS ABIs 2023-04-27 11:37:12 +02:00
3112ef0e95 Merge pull request 'Add reinitializer for upgrades to Contributor' (#239) from feature/upgrade_reinitializers into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #239
2023-04-27 09:34:25 +00:00
Râu Cao
d63f7ca743
Add reinitializer for upgrades to Contributor
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
In order to be able to re-initialize the upgraded contract with the
profile manager address, we need a new re-initializer function that is
automatically allowed to only be executed once per contract
implementation version.

Co-authored-by: Michael Bumann <hello@michaelbumann.com>
2023-04-27 11:11:30 +02:00
f10af14fae Merge pull request 'Fix variable sort order in contract' (#238) from bugfix/variables into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #238
2023-04-27 09:07:50 +00:00
Râu Cao
2692613b9a
Fix variable sort order in contract
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
New variables have to be added at the end, because otherwise the
existing slots would be mixed up.

Co-authored-by: Michael Bumann <hello@michaelbumann.com>
2023-04-27 11:05:57 +02:00
Râu Cao
b49d1130a9
7.1.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-26 15:49:57 +02:00
Râu Cao
657cdc8afa
Update JS ABIs 2023-04-26 15:49:44 +02:00
Râu Cao
ae9aa7aaaf
Update seeds 2023-04-26 15:47:01 +02:00
Râu Cao
708515ba4b
Add emit statement for event 2023-04-26 15:46:41 +02:00
7eceea5d57 Merge pull request 'Fix wrapper function: Reimbursement.getData()' (#237) from bugfix/reimbursement_get-data into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #237
2023-04-26 13:44:14 +00:00
Râu Cao
089ffd42fe
Fix wrapper function: Reimbursement.getData()
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-04-26 15:42:17 +02:00
Râu Cao
43d9bc0a07
Add missing profile manager address to seeds
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-25 16:38:02 +02:00
Râu Cao
6113e456af
Add release drafter action configs
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-11 23:13:05 +02:00
8ef6fc06ce Merge pull request 'Allow a profile manager key to add contributor profiles' (#236) from feature/profile_manager into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #236
2023-04-11 21:06:42 +00:00
Râu Cao
093273f15b
Allow a profile manager key to add contributor profiles
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
The profile manager is usually a bot that can also auth users against
external sources to prevent spam and integrate with existing Web
services.
2023-03-22 19:11:37 +07:00
Râu Cao
1dc54eccea
Update seeds
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-22 18:15:51 +07:00
Râu Cao
bb662e377c
Update README
All checks were successful
continuous-integration/drone/push Build is passing
* Add build status badge
* Add section about testing
* Formatting
2023-03-22 18:14:12 +07:00
Râu Cao
d6bbc441f8
Update package name in lockfile
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-19 14:52:32 +08:00
Râu Cao
46090b3740
Update README
All checks were successful
continuous-integration/drone/push Build is passing
2022-11-04 12:27:16 +01:00
Râu Cao
828f831c52
7.0.1
All checks were successful
continuous-integration/drone/push Build is passing
2022-11-02 19:07:56 +01:00
Râu Cao
500180c6da
Update npm badge
Some checks are pending
continuous-integration/drone/push Build is running
2022-11-02 19:07:42 +01:00
32 changed files with 1272 additions and 105 deletions

View File

@ -0,0 +1,14 @@
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
version-resolver:
major:
labels:
- release/major
minor:
labels:
- release/minor
- feature
patch:
labels:
- release/patch
default: patch

View File

@ -0,0 +1,11 @@
name: Release Drafter
on:
pull_request:
types: [closed]
jobs:
release_drafter_job:
name: Update release notes draft
runs-on: ubuntu-latest
steps:
- name: Release Drafter
uses: https://github.com/raucao/gitea-release-drafter@dev

3
.gitignore vendored
View File

@ -9,4 +9,5 @@ data
cache
artifacts
.openzeppelin
.openzeppelin/unknown-1337.json
.env

0
.openzeppelin/.keep Normal file
View File

View File

@ -0,0 +1,937 @@
{
"manifestVersion": "3.2",
"admin": {
"address": "0xcf844786B3E8b23f6d6D8CA845c0DE07047D54a7",
"txHash": "0xafcf40769c999bae279f48e7d81d0f698c82286dd4178029021f82ecb549e645"
},
"proxies": [
{
"address": "0x0E4b2A1b7655266Ba9A029B50eEB42DBCd83090B",
"txHash": "0xfd629e11999d0448404c81e33ea79cbd18f8a978cf93afcf5c45e97eb63991f8",
"kind": "transparent"
},
{
"address": "0x242fab10d4F395B9DCC59b8Adc6629722c2E65d2",
"txHash": "0xcd6633873db24736e9f40a4c401b658b469b290176e0d03e640ccfb7945a5426",
"kind": "transparent"
},
{
"address": "0x4fe4311a91F90ff98f0978002D84AE4771fe7cF1",
"txHash": "0x8b6e5088ad7f39918bf9e3e67cdc45bd9bf2a62b13e4f7a1441ad3bca27b4c04",
"kind": "transparent"
},
{
"address": "0x252b3Ab7913d6Ed8f303a7e5452F0BFf8bE6b64d",
"txHash": "0x138a863f21ab0ef2400434280bc8c9e389e6dead125b5622deb9533eb2506a53",
"kind": "transparent"
},
{
"address": "0x2C5cf87C0dE8e4E3642de900Fa7B4b630163E2aA",
"txHash": "0x0e4310cd5faba8ce7cae60b3de1412050b4315957e58bc8415680eb5e9de0314",
"kind": "transparent"
},
{
"address": "0x95DC31665D193E377f54b70C535fcDb205525291",
"txHash": "0xb03a4d57e80f73d65f29f75fc419fd6197148e979ed9c330353c8574d952c544",
"kind": "transparent"
},
{
"address": "0x049bA8E70FEbFfd6d03C71211bDA37B4ff064115",
"txHash": "0x5f561059950c1e06fc62cfc7cac4c4618a0e066704fb680b659ae9a08b6e1d27",
"kind": "transparent"
},
{
"address": "0x7ab26A0f00eF0D6e05e5BDE047505a4eD53aF809",
"txHash": "0xfa73dbe843ea1151f925f531365fb919b6138c8963e62332c8e00cf5141e457c",
"kind": "transparent"
},
{
"address": "0x99EC72b34295b62f4bC1527Da461262c615a0b2c",
"txHash": "0x1ca664ffdf50a6519b900c84e715d43a59ae39b35d5914ecb964f5440d486098",
"kind": "transparent"
}
],
"impls": {
"4ef0a0d41e92c95e53ad65fb957441f9b9443f4fe2d1c2221dfde7d1341db071": {
"address": "0x73069A23A5252E9c0D0b5F0493918277074ED987",
"txHash": "0x4c139a7a70dea23d9fdbcb7d8d381be7593fc3d80d59f29aec0fd6f16698136b",
"layout": {
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "deployer",
"offset": 2,
"slot": "0",
"type": "t_address",
"contract": "Contributor",
"src": "contracts/Contributor.sol:15"
},
{
"label": "contributionContract",
"offset": 0,
"slot": "1",
"type": "t_contract(IContributionBalance)2238",
"contract": "Contributor",
"src": "contracts/Contributor.sol:16"
},
{
"label": "tokenContract",
"offset": 0,
"slot": "2",
"type": "t_contract(IToken)2221",
"contract": "Contributor",
"src": "contracts/Contributor.sol:17"
},
{
"label": "contributorIds",
"offset": 0,
"slot": "3",
"type": "t_mapping(t_address,t_uint32)",
"contract": "Contributor",
"src": "contracts/Contributor.sol:28"
},
{
"label": "contributors",
"offset": 0,
"slot": "4",
"type": "t_mapping(t_uint32,t_struct(Contributor)2261_storage)",
"contract": "Contributor",
"src": "contracts/Contributor.sol:29"
},
{
"label": "contributorsCount",
"offset": 0,
"slot": "5",
"type": "t_uint32",
"contract": "Contributor",
"src": "contracts/Contributor.sol:30"
},
{
"label": "profileManager",
"offset": 4,
"slot": "5",
"type": "t_address",
"contract": "Contributor",
"src": "contracts/Contributor.sol:32"
}
],
"types": {
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(IContributionBalance)2238": {
"label": "contract IContributionBalance",
"numberOfBytes": "20"
},
"t_contract(IToken)2221": {
"label": "contract IToken",
"numberOfBytes": "20"
},
"t_mapping(t_address,t_uint32)": {
"label": "mapping(address => uint32)",
"numberOfBytes": "32"
},
"t_mapping(t_uint32,t_struct(Contributor)2261_storage)": {
"label": "mapping(uint32 => struct Contributor.Contributor)",
"numberOfBytes": "32"
},
"t_struct(Contributor)2261_storage": {
"label": "struct Contributor.Contributor",
"members": [
{
"label": "account",
"type": "t_address",
"offset": 0,
"slot": "0"
},
{
"label": "hashDigest",
"type": "t_bytes32",
"offset": 0,
"slot": "1"
},
{
"label": "hashFunction",
"type": "t_uint8",
"offset": 0,
"slot": "2"
},
{
"label": "hashSize",
"type": "t_uint8",
"offset": 1,
"slot": "2"
},
{
"label": "exists",
"type": "t_bool",
"offset": 2,
"slot": "2"
},
{
"label": "kreditsWithdrawn",
"type": "t_uint32",
"offset": 3,
"slot": "2"
}
],
"numberOfBytes": "96"
},
"t_uint32": {
"label": "uint32",
"numberOfBytes": "4"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
},
"960de0fa0d50c2ede5b2a868a9475e44622a753d4ff7829422c7eb342572b189": {
"address": "0x872fa1C9d207b5ce3CE786f2099c3EeA621dFD70",
"txHash": "0xb338b0878d66e466425c9032ef0f9019f91cda395fae4f83c999534249cd228d",
"layout": {
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "contributorContract",
"offset": 2,
"slot": "0",
"type": "t_contract(ContributorInterface)1546",
"contract": "Contribution",
"src": "contracts/Contribution.sol:14"
},
{
"label": "name_",
"offset": 0,
"slot": "1",
"type": "t_string_storage",
"contract": "Contribution",
"src": "contracts/Contribution.sol:28"
},
{
"label": "symbol_",
"offset": 0,
"slot": "2",
"type": "t_string_storage",
"contract": "Contribution",
"src": "contracts/Contribution.sol:29"
},
{
"label": "contributionOwner",
"offset": 0,
"slot": "3",
"type": "t_mapping(t_uint32,t_uint32)",
"contract": "Contribution",
"src": "contracts/Contribution.sol:32"
},
{
"label": "ownedContributions",
"offset": 0,
"slot": "4",
"type": "t_mapping(t_uint32,t_array(t_uint32)dyn_storage)",
"contract": "Contribution",
"src": "contracts/Contribution.sol:34"
},
{
"label": "contributions",
"offset": 0,
"slot": "5",
"type": "t_mapping(t_uint32,t_struct(ContributionData)1570_storage)",
"contract": "Contribution",
"src": "contracts/Contribution.sol:36"
},
{
"label": "contributionsCount",
"offset": 0,
"slot": "6",
"type": "t_uint32",
"contract": "Contribution",
"src": "contracts/Contribution.sol:37"
},
{
"label": "blocksToWait",
"offset": 4,
"slot": "6",
"type": "t_uint32",
"contract": "Contribution",
"src": "contracts/Contribution.sol:40"
},
{
"label": "deployer",
"offset": 8,
"slot": "6",
"type": "t_address",
"contract": "Contribution",
"src": "contracts/Contribution.sol:43"
},
{
"label": "migrationDone",
"offset": 28,
"slot": "6",
"type": "t_bool",
"contract": "Contribution",
"src": "contracts/Contribution.sol:46"
}
],
"types": {
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_array(t_uint32)dyn_storage": {
"label": "uint32[]",
"numberOfBytes": "32"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(ContributorInterface)1546": {
"label": "contract ContributorInterface",
"numberOfBytes": "20"
},
"t_mapping(t_uint32,t_array(t_uint32)dyn_storage)": {
"label": "mapping(uint32 => uint32[])",
"numberOfBytes": "32"
},
"t_mapping(t_uint32,t_struct(ContributionData)1570_storage)": {
"label": "mapping(uint32 => struct Contribution.ContributionData)",
"numberOfBytes": "32"
},
"t_mapping(t_uint32,t_uint32)": {
"label": "mapping(uint32 => uint32)",
"numberOfBytes": "32"
},
"t_string_storage": {
"label": "string",
"numberOfBytes": "32"
},
"t_struct(ContributionData)1570_storage": {
"label": "struct Contribution.ContributionData",
"members": [
{
"label": "contributorId",
"type": "t_uint32",
"offset": 0,
"slot": "0"
},
{
"label": "amount",
"type": "t_uint32",
"offset": 4,
"slot": "0"
},
{
"label": "hashDigest",
"type": "t_bytes32",
"offset": 0,
"slot": "1"
},
{
"label": "hashFunction",
"type": "t_uint8",
"offset": 0,
"slot": "2"
},
{
"label": "hashSize",
"type": "t_uint8",
"offset": 1,
"slot": "2"
},
{
"label": "tokenMetadataURL",
"type": "t_string_storage",
"offset": 0,
"slot": "3"
},
{
"label": "confirmedAtBlock",
"type": "t_uint256",
"offset": 0,
"slot": "4"
},
{
"label": "vetoed",
"type": "t_bool",
"offset": 0,
"slot": "5"
},
{
"label": "exists",
"type": "t_bool",
"offset": 1,
"slot": "5"
}
],
"numberOfBytes": "192"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint32": {
"label": "uint32",
"numberOfBytes": "4"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
},
"75d216a88a04f139c0c69c1369ddd6ded974ebf995ccce44546b6ace2dabb597": {
"address": "0x2D7848AF9Af0d2d8D67bbaAbf84D58Bd19F17eFa",
"txHash": "0x8a6621bfc3db4c2bc2d294d69e6d25d499c7667b8da1910b3b0f2bc43968adba",
"layout": {
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "__gap",
"offset": 0,
"slot": "1",
"type": "t_array(t_uint256)50_storage",
"contract": "ContextUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36"
},
{
"label": "_balances",
"offset": 0,
"slot": "51",
"type": "t_mapping(t_address,t_uint256)",
"contract": "ERC20Upgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:37"
},
{
"label": "_allowances",
"offset": 0,
"slot": "52",
"type": "t_mapping(t_address,t_mapping(t_address,t_uint256))",
"contract": "ERC20Upgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:39"
},
{
"label": "_totalSupply",
"offset": 0,
"slot": "53",
"type": "t_uint256",
"contract": "ERC20Upgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:41"
},
{
"label": "_name",
"offset": 0,
"slot": "54",
"type": "t_string_storage",
"contract": "ERC20Upgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:43"
},
{
"label": "_symbol",
"offset": 0,
"slot": "55",
"type": "t_string_storage",
"contract": "ERC20Upgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44"
},
{
"label": "__gap",
"offset": 0,
"slot": "56",
"type": "t_array(t_uint256)45_storage",
"contract": "ERC20Upgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:400"
},
{
"label": "contributorContract",
"offset": 0,
"slot": "101",
"type": "t_contract(ContributorInterface)3364",
"contract": "Token",
"src": "contracts/Token.sol:13"
},
{
"label": "contributorContractAddress",
"offset": 0,
"slot": "102",
"type": "t_address",
"contract": "Token",
"src": "contracts/Token.sol:16"
}
],
"types": {
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_array(t_uint256)45_storage": {
"label": "uint256[45]",
"numberOfBytes": "1440"
},
"t_array(t_uint256)50_storage": {
"label": "uint256[50]",
"numberOfBytes": "1600"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_contract(ContributorInterface)3364": {
"label": "contract ContributorInterface",
"numberOfBytes": "20"
},
"t_mapping(t_address,t_mapping(t_address,t_uint256))": {
"label": "mapping(address => mapping(address => uint256))",
"numberOfBytes": "32"
},
"t_mapping(t_address,t_uint256)": {
"label": "mapping(address => uint256)",
"numberOfBytes": "32"
},
"t_string_storage": {
"label": "string",
"numberOfBytes": "32"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
},
"d06fbc00ef593e162a054b1f961d39eaf32e0734f8ba230d3519837b8548e33b": {
"address": "0x5b8AF16247593465cC82b68A7Af49338E141A207",
"txHash": "0x2e052dd42231aa43a484c5a4c376e73b70fd14026611be0b585c826d37fe829c",
"layout": {
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "contributorContract",
"offset": 2,
"slot": "0",
"type": "t_contract(ContributorInterface)2958",
"contract": "Reimbursement",
"src": "contracts/Reimbursement.sol:14"
},
{
"label": "reimbursements",
"offset": 0,
"slot": "1",
"type": "t_mapping(t_uint32,t_struct(ReimbursementData)2982_storage)",
"contract": "Reimbursement",
"src": "contracts/Reimbursement.sol:29"
},
{
"label": "reimbursementsCount",
"offset": 0,
"slot": "2",
"type": "t_uint32",
"contract": "Reimbursement",
"src": "contracts/Reimbursement.sol:30"
},
{
"label": "blocksToWait",
"offset": 4,
"slot": "2",
"type": "t_uint32",
"contract": "Reimbursement",
"src": "contracts/Reimbursement.sol:32"
}
],
"types": {
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(ContributorInterface)2958": {
"label": "contract ContributorInterface",
"numberOfBytes": "20"
},
"t_mapping(t_uint32,t_struct(ReimbursementData)2982_storage)": {
"label": "mapping(uint32 => struct Reimbursement.ReimbursementData)",
"numberOfBytes": "32"
},
"t_struct(ReimbursementData)2982_storage": {
"label": "struct Reimbursement.ReimbursementData",
"members": [
{
"label": "recipientId",
"type": "t_uint32",
"offset": 0,
"slot": "0"
},
{
"label": "amount",
"type": "t_uint256",
"offset": 0,
"slot": "1"
},
{
"label": "token",
"type": "t_address",
"offset": 0,
"slot": "2"
},
{
"label": "hashDigest",
"type": "t_bytes32",
"offset": 0,
"slot": "3"
},
{
"label": "hashFunction",
"type": "t_uint8",
"offset": 0,
"slot": "4"
},
{
"label": "hashSize",
"type": "t_uint8",
"offset": 1,
"slot": "4"
},
{
"label": "confirmedAtBlock",
"type": "t_uint256",
"offset": 0,
"slot": "5"
},
{
"label": "vetoed",
"type": "t_bool",
"offset": 0,
"slot": "6"
},
{
"label": "exists",
"type": "t_bool",
"offset": 1,
"slot": "6"
}
],
"numberOfBytes": "224"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint32": {
"label": "uint32",
"numberOfBytes": "4"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
},
"27e6fdeedf4e7e81a2c2ecc839d0c13414aa8f5527d4d3573f469358c8aad652": {
"address": "0xfaeA425E6eDd4e9B31dAa3614c7c7862751D6782",
"txHash": "0xe7768586dbfb5d528db3c9d0c2a608a4fcb5d7f04eb9f89913ac21b8d20a72df",
"layout": {
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "contributorContract",
"offset": 2,
"slot": "0",
"type": "t_contract(ContributorInterface)1546",
"contract": "Contribution",
"src": "contracts/Contribution.sol:14"
},
{
"label": "name_",
"offset": 0,
"slot": "1",
"type": "t_string_storage",
"contract": "Contribution",
"src": "contracts/Contribution.sol:28"
},
{
"label": "symbol_",
"offset": 0,
"slot": "2",
"type": "t_string_storage",
"contract": "Contribution",
"src": "contracts/Contribution.sol:29"
},
{
"label": "contributionOwner",
"offset": 0,
"slot": "3",
"type": "t_mapping(t_uint32,t_uint32)",
"contract": "Contribution",
"src": "contracts/Contribution.sol:32"
},
{
"label": "ownedContributions",
"offset": 0,
"slot": "4",
"type": "t_mapping(t_uint32,t_array(t_uint32)dyn_storage)",
"contract": "Contribution",
"src": "contracts/Contribution.sol:34"
},
{
"label": "contributions",
"offset": 0,
"slot": "5",
"type": "t_mapping(t_uint32,t_struct(ContributionData)1570_storage)",
"contract": "Contribution",
"src": "contracts/Contribution.sol:36"
},
{
"label": "contributionsCount",
"offset": 0,
"slot": "6",
"type": "t_uint32",
"contract": "Contribution",
"src": "contracts/Contribution.sol:37"
},
{
"label": "blocksToWait",
"offset": 4,
"slot": "6",
"type": "t_uint32",
"contract": "Contribution",
"src": "contracts/Contribution.sol:40"
},
{
"label": "deployer",
"offset": 8,
"slot": "6",
"type": "t_address",
"contract": "Contribution",
"src": "contracts/Contribution.sol:43"
},
{
"label": "migrationDone",
"offset": 28,
"slot": "6",
"type": "t_bool",
"contract": "Contribution",
"src": "contracts/Contribution.sol:46"
}
],
"types": {
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_array(t_uint32)dyn_storage": {
"label": "uint32[]",
"numberOfBytes": "32"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(ContributorInterface)1546": {
"label": "contract ContributorInterface",
"numberOfBytes": "20"
},
"t_mapping(t_uint32,t_array(t_uint32)dyn_storage)": {
"label": "mapping(uint32 => uint32[])",
"numberOfBytes": "32"
},
"t_mapping(t_uint32,t_struct(ContributionData)1570_storage)": {
"label": "mapping(uint32 => struct Contribution.ContributionData)",
"numberOfBytes": "32"
},
"t_mapping(t_uint32,t_uint32)": {
"label": "mapping(uint32 => uint32)",
"numberOfBytes": "32"
},
"t_string_storage": {
"label": "string",
"numberOfBytes": "32"
},
"t_struct(ContributionData)1570_storage": {
"label": "struct Contribution.ContributionData",
"members": [
{
"label": "contributorId",
"type": "t_uint32",
"offset": 0,
"slot": "0"
},
{
"label": "amount",
"type": "t_uint32",
"offset": 4,
"slot": "0"
},
{
"label": "hashDigest",
"type": "t_bytes32",
"offset": 0,
"slot": "1"
},
{
"label": "hashFunction",
"type": "t_uint8",
"offset": 0,
"slot": "2"
},
{
"label": "hashSize",
"type": "t_uint8",
"offset": 1,
"slot": "2"
},
{
"label": "tokenMetadataURL",
"type": "t_string_storage",
"offset": 0,
"slot": "3"
},
{
"label": "confirmedAtBlock",
"type": "t_uint256",
"offset": 0,
"slot": "4"
},
{
"label": "vetoed",
"type": "t_bool",
"offset": 0,
"slot": "5"
},
{
"label": "exists",
"type": "t_bool",
"offset": 1,
"slot": "5"
}
],
"numberOfBytes": "192"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint32": {
"label": "uint32",
"numberOfBytes": "4"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
}
}
}

View File

@ -4,6 +4,6 @@
"solhint:recommended"
],
"rules": {
"indent": "2"
"max-line-length": "warn"
}
}

View File

@ -1,4 +1,5 @@
[![npm](https://img.shields.io/npm/v/kredits-contracts.svg)](https://www.npmjs.com/package/kredits-contracts)
[![npm](https://img.shields.io/npm/v/@kredits/contracts.svg)](https://www.npmjs.com/package/@kredits/contracts)
[![Build Status](https://drone.kosmos.org/api/badges/kredits/contracts/status.svg)](https://drone.kosmos.org/kredits/contracts)
# Kredits Contracts
@ -26,7 +27,7 @@ To run a local development chain run:
### Bootstrap
1. Run an Ethereum node and ipfs
1. Run an EVM node and ipfs
$ npm run devchain
$ ipfs daemon
@ -56,6 +57,16 @@ If you need to fund development accounts with devchain coins:
$ npm run fund # or hardhat fund --network localhost
## Specs / Testing
With a local development chain running:
$ hardhat test
If you add or change contract code, please make sure to add and/or adapt tests
accordingly. Don't worry, it's easy! You can use existing tests as a template
for new ones.
## Contract architecture
We use the [OpenZeppelin hardhat
@ -145,12 +156,3 @@ To run the console on one of the non localhost networks you can also just pass
on the --network argument.
$ hardhat console --network rsk
## Known Issues
When resetting ganache Metamask might have an invalid transaction nonce and
transactions get rejected. Nonces in Ethereum must be incrementing and have no
gap.
To solve this reset the metamask account (Account -> Settings -> Reset Account)

View File

@ -15,7 +15,7 @@ const contractCalls = [
name: 'raucao',
kind: 'person',
url: '',
github_username: 'skddc',
github_username: 'raucao',
github_uid: 842,
gitea_username: 'raucao',
wiki_username: 'Basti',
@ -31,18 +31,55 @@ const contractCalls = [
wiki_username: 'Manuel',
}, { gasLimit: 200000 }]],
['Contribution', 'add', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-11', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Test this thing', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'add', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-11', amount: 1500, kind: 'dev', description: '[67P/kredits-web] Reviewed stuff', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'add', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-11', amount: 1500, kind: 'dev', description: '[67P/kredits-contracts] Add tests', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'add', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-11', amount: 1500, kind: 'dev', description: '[67P/kredits-contracts] Introduce contribution token', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'add', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-11', amount: 5000, kind: 'dev', description: '[67P/kredits-web] Expense UI, first draft', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'add', [{
contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF',
date: '2019-04-11', amount: 500, kind: 'dev',
description: '[67P/kredits-contracts] Test this thing',
url: '',
confirmedAtBlock: 1,
}, { gasLimit: 350000 }]],
['Contribution', 'add', [{
contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB',
date: '2019-04-11', amount: 1500, kind: 'dev',
description: '[67P/kredits-web] Reviewed stuff',
url: '',
confirmedAtBlock: 1,
}, { gasLimit: 350000 }]],
['Contribution', 'add', [{
contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF',
date: '2019-04-11', amount: 5000, kind: 'dev',
description: '[67P/kredits-contracts] Add tests',
url: '',
confirmedAtBlock: 1,
}, { gasLimit: 350000 }]],
['Contribution', 'add', [{
contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF',
date: '2019-04-11', amount: 1500, kind: 'dev',
description: '[67P/kredits-contracts] Introduce contribution token',
url: '',
}, { gasLimit: 350000 }]],
['Contribution', 'add', [{
contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB',
date: '2019-04-11', amount: 1500, kind: 'design',
description: '[67P/kredits-web] Expense UI, first draft',
url: '',
}, { gasLimit: 350000 }]],
['Reimbursement', 'add', [{ amount: 346800, recipientId: 2, token: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', expenses: [
{ title: 'Domain kosmos.social', description: 'Yearly registration fee for domain kosmos.social', amount: 69.00, currency: 'EUR', amountSats: 69216, date: '2020-04-30' },
], confirmedAtBlock: 1 }, { gasLimit: 300000 }]],
['Reimbursement', 'add', [{ amount: 1116000, recipientId: 1, token: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', expenses: [
{ title: 'Server rent', description: 'Dedicated server: andromeda.kosmos.org, April 2020', amount: 61, currency: 'EUR', date: '2020-05-28' },
{ title: 'Server rent', description: 'Dedicated server: centaurus.kosmos.org, April 2020', amount: 32, currency: 'EUR', date: '2020-05-28' }
]}, { gasLimit: 300000 }]],
{ title: 'Server rent', description: 'Dedicated server: andromeda.kosmos.org, April 2020', amount: 61, currency: 'EUR', amountSats: 61191, date: '2020-05-28' },
{ title: 'Server rent', description: 'Dedicated server: centaurus.kosmos.org, April 2020', amount: 32, currency: 'EUR', amountSats: 32201, date: '2020-05-28' },
], confirmedAtBlock: 1 }, { gasLimit: 300000 }]],
['Reimbursement', 'add', [{ amount: 166800, recipientId: 2, token: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', expenses: [
{ title: 'Domain kosmos.chat', description: 'Yearly registration fee for domain kosmos.chat', amount: 13.90, currency: 'EUR', date: '2020-05-30' }
{ title: 'Domain kosmos.chat', description: 'Yearly registration fee for domain kosmos.chat', amount: 13.90, currency: 'EUR', amountSats: 13944, date: '2020-05-30' },
]}, { gasLimit: 300000 }]],
];

View File

@ -95,13 +95,13 @@ contract Contribution is Initializable {
// Balance is amount of ERC271 tokens, not amount of kredits
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0));
require(owner != address(0), "Address invalid");
uint32 contributorId = getContributorIdByAddress(owner);
return ownedContributions[contributorId].length;
}
function ownerOf(uint32 contributionId) public view returns (address) {
require(exists(contributionId));
require(exists(contributionId), "Contribution does not exist");
uint32 contributorId = contributions[contributionId].contributorId;
return getContributorAddressById(contributorId);
}
@ -156,10 +156,8 @@ contract Contribution is Initializable {
}
function add(uint32 amount, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool vetoed) public {
// require(canPerform(msg.sender, ADD_CONTRIBUTION_ROLE, new uint32[](0)), 'nope');
// TODO hubot neither has kredits nor a core account
require((confirmedAtBlock == 0 && vetoed == false) || migrationDone == false, 'extra arguments during migration only');
require(balanceOf(msg.sender) > 0 || contributorContract.addressIsCore(msg.sender), 'requires kredits or core status');
require((confirmedAtBlock == 0 && vetoed == false) || migrationDone == false, "Extra arguments not allowed");
require(balanceOf(msg.sender) > 0 || contributorContract.addressIsCore(msg.sender), "Requires kredits or core status");
uint32 contributionId = contributionsCount + 1;
ContributionData storage c = contributions[contributionId];
@ -188,8 +186,8 @@ contract Contribution is Initializable {
function veto(uint32 contributionId) public onlyCore {
ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND');
require(block.number < c.confirmedAtBlock, 'VETO_PERIOD_ENDED');
require(c.exists, "NOT_FOUND");
require(block.number < c.confirmedAtBlock, "VETO_PERIOD_ENDED");
c.vetoed = true;
emit ContributionVetoed(contributionId, msg.sender);

View File

@ -29,6 +29,8 @@ contract Contributor is Initializable {
mapping (uint32 => Contributor) public contributors;
uint32 public contributorsCount;
address public profileManager;
event ContributorProfileUpdated(uint32 id, bytes32 oldHashDigest, bytes32 newHashDigest); // what should be logged
event ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
event ContributorAdded(uint32 id, address account);
@ -43,8 +45,13 @@ contract Contributor is Initializable {
_;
}
function initialize() public initializer {
function initialize(address profileManagerAddress) public initializer {
deployer = msg.sender;
profileManager = profileManagerAddress;
}
function reinitialize(address profileManagerAddress) public reinitializer(2) {
profileManager = profileManagerAddress;
}
function setContributionContract(address contribution) public onlyCore {
@ -84,11 +91,12 @@ contract Contributor is Initializable {
c.hashFunction = hashFunction;
c.hashSize = hashSize;
ContributorProfileUpdated(id, oldHashDigest, c.hashDigest);
emit ContributorProfileUpdated(id, oldHashDigest, c.hashDigest);
}
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public onlyCore {
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public {
require(!addressExists(account), "Address already in use");
require((msg.sender == profileManager) || addressIsCore(msg.sender), "Only core and profile manager");
uint32 _id = contributorsCount + 1;
assert(!contributors[_id].exists); // this can not be acually
Contributor storage c = contributors[_id];
@ -104,17 +112,17 @@ contract Contributor is Initializable {
emit ContributorAdded(_id, account);
}
function isCoreTeam(uint32 id) view public returns (bool) {
function isCoreTeam(uint32 id) public view returns (bool) {
// TODO: for simplicity we simply define the first contributors as core
// later this needs to be changed to something more dynamic
return id > 0 && id < 7;
}
function exists(uint32 id) view public returns (bool) {
function exists(uint32 id) public view returns (bool) {
return contributors[id].exists;
}
function addressIsCore(address account) view public returns (bool) {
function addressIsCore(address account) public view returns (bool) {
// the deployer is always core
if(account == deployer) {
return true;
@ -123,15 +131,15 @@ contract Contributor is Initializable {
return isCoreTeam(id);
}
function addressExists(address account) view public returns (bool) {
function addressExists(address account) public view returns (bool) {
return getContributorByAddress(account).exists;
}
function getContributorIdByAddress(address account) view public returns (uint32) {
function getContributorIdByAddress(address account) public view returns (uint32) {
return contributorIds[account];
}
function getContributorAddressById(uint32 id) view public returns (address) {
function getContributorAddressById(uint32 id) public view returns (address) {
return contributors[id].account;
}
@ -140,7 +148,7 @@ contract Contributor is Initializable {
return contributors[id];
}
function getContributorById(uint32 _id) view public returns (uint32 id, address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, uint32 totalKreditsEarned, uint256 contributionsCount, bool exists, uint256 kreditsWithdrawn) {
function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, uint32 totalKreditsEarned, uint256 contributionsCount, bool exists, uint256 kreditsWithdrawn) {
id = _id;
Contributor storage c = contributors[_id];
account = c.account;

View File

@ -16,6 +16,7 @@ contract Reimbursement is Initializable {
struct ReimbursementData {
uint32 recipientId;
uint256 amount;
// TODO remove token entirely
address token;
bytes32 hashDigest;
uint8 hashFunction;
@ -30,18 +31,35 @@ contract Reimbursement is Initializable {
uint32 public blocksToWait;
// The address that deployed the contract
address public deployer;
// Data migration flag
bool public migrationDone;
event ReimbursementAdded(uint32 id, address indexed addedByAccount, uint256 amount);
event ReimbursementVetoed(uint32 id, address vetoedByAccount);
function initialize() public initializer {
blocksToWait = 40320; // 7 days; 15 seconds block time
}
modifier onlyCore {
require(contributorContract.addressIsCore(tx.origin), "Core only");
_;
}
modifier onlyDeployer {
require(msg.sender == deployer, "Deployer only");
_;
}
function initialize() public initializer {
deployer = msg.sender;
migrationDone = false;
blocksToWait = 40320; // 7 days; 15 seconds block time
}
function finishMigration() public onlyDeployer {
migrationDone = true;
}
function setContributorContract(address contributor) public {
require(address(contributorContract) == address(0) || contributorContract.addressIsCore(msg.sender), "Core only");
contributorContract = ContributorInterface(contributor);
@ -81,7 +99,8 @@ contract Reimbursement is Initializable {
);
}
function add(uint256 amount, address token, uint32 recipientId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public onlyCore {
function add(uint256 amount, address token, uint32 recipientId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool vetoed) public onlyCore {
require((confirmedAtBlock == 0 && vetoed == false) || migrationDone == false, "Extra arguments not allowed");
uint32 reimbursementId = reimbursementsCount + 1;
ReimbursementData storage r = reimbursements[reimbursementId];
r.exists = true;
@ -91,7 +110,14 @@ contract Reimbursement is Initializable {
r.hashDigest = hashDigest;
r.hashFunction = hashFunction;
r.hashSize = hashSize;
r.confirmedAtBlock = block.number + blocksToWait;
if (confirmedAtBlock > 0) {
r.confirmedAtBlock = confirmedAtBlock;
} else {
r.confirmedAtBlock = block.number + 1 + blocksToWait;
}
if (vetoed) { r.vetoed = true; }
reimbursementsCount++;
@ -100,8 +126,8 @@ contract Reimbursement is Initializable {
function veto(uint32 reimbursementId) public onlyCore {
ReimbursementData storage r = reimbursements[reimbursementId];
require(r.exists, 'NOT_FOUND');
require(block.number < r.confirmedAtBlock, 'VETO_PERIOD_ENDED');
require(r.exists, "NOT_FOUND");
require(block.number < r.confirmedAtBlock, "VETO_PERIOD_ENDED");
r.vetoed = true;
emit ReimbursementVetoed(reimbursementId, msg.sender);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"id","type":"uint32"},{"indexed":true,"internalType":"address","name":"addedByAccount","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReimbursementAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"id","type":"uint32"},{"indexed":false,"internalType":"address","name":"vetoedByAccount","type":"address"}],"name":"ReimbursementVetoed","type":"event"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32","name":"recipientId","type":"uint32"},{"internalType":"bytes32","name":"hashDigest","type":"bytes32"},{"internalType":"uint8","name":"hashFunction","type":"uint8"},{"internalType":"uint8","name":"hashSize","type":"uint8"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blocksToWait","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContract","outputs":[{"internalType":"contract ContributorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"reimbursementId","type":"uint32"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"reimbursementId","type":"uint32"}],"name":"get","outputs":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"recipientId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"hashDigest","type":"bytes32"},{"internalType":"uint8","name":"hashFunction","type":"uint8"},{"internalType":"uint8","name":"hashSize","type":"uint8"},{"internalType":"uint256","name":"confirmedAtBlock","type":"uint256"},{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"bool","name":"vetoed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"contributorId","type":"uint32"}],"name":"getContributorAddressById","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributorAccount","type":"address"}],"name":"getContributorIdByAddress","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"reimbursements","outputs":[{"internalType":"uint32","name":"recipientId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"hashDigest","type":"bytes32"},{"internalType":"uint8","name":"hashFunction","type":"uint8"},{"internalType":"uint8","name":"hashSize","type":"uint8"},{"internalType":"uint256","name":"confirmedAtBlock","type":"uint256"},{"internalType":"bool","name":"vetoed","type":"bool"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reimbursementsCount","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"setContributorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"confirmedOnly","type":"bool"}],"name":"totalAmount","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"reimbursementId","type":"uint32"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"}]
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"id","type":"uint32"},{"indexed":true,"internalType":"address","name":"addedByAccount","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReimbursementAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"id","type":"uint32"},{"indexed":false,"internalType":"address","name":"vetoedByAccount","type":"address"}],"name":"ReimbursementVetoed","type":"event"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32","name":"recipientId","type":"uint32"},{"internalType":"bytes32","name":"hashDigest","type":"bytes32"},{"internalType":"uint8","name":"hashFunction","type":"uint8"},{"internalType":"uint8","name":"hashSize","type":"uint8"},{"internalType":"uint256","name":"confirmedAtBlock","type":"uint256"},{"internalType":"bool","name":"vetoed","type":"bool"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blocksToWait","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContract","outputs":[{"internalType":"contract ContributorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"reimbursementId","type":"uint32"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finishMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"reimbursementId","type":"uint32"}],"name":"get","outputs":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"recipientId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"hashDigest","type":"bytes32"},{"internalType":"uint8","name":"hashFunction","type":"uint8"},{"internalType":"uint8","name":"hashSize","type":"uint8"},{"internalType":"uint256","name":"confirmedAtBlock","type":"uint256"},{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"bool","name":"vetoed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"contributorId","type":"uint32"}],"name":"getContributorAddressById","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributorAccount","type":"address"}],"name":"getContributorIdByAddress","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrationDone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"reimbursements","outputs":[{"internalType":"uint32","name":"recipientId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"hashDigest","type":"bytes32"},{"internalType":"uint8","name":"hashFunction","type":"uint8"},{"internalType":"uint8","name":"hashSize","type":"uint8"},{"internalType":"uint256","name":"confirmedAtBlock","type":"uint256"},{"internalType":"bool","name":"vetoed","type":"bool"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reimbursementsCount","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"setContributorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"confirmedOnly","type":"bool"}],"name":"totalAmount","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"reimbursementId","type":"uint32"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"}]

View File

@ -1 +1 @@
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"KreditsMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContract","outputs":[{"internalType":"contract ContributorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributorAccount","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"setContributorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"KreditsMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContract","outputs":[{"internalType":"contract ContributorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contributorContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contributorAccount","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contributor","type":"address"}],"name":"setContributorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

View File

@ -1,9 +1,9 @@
{
"31": {
"Contributor": "0xf1073Dab6e305583F95e451Cba449bB867a6e3Fd",
"Contribution": "0x1C531F824e339cD37D75B7F391cB8E42e0E0d4bd",
"Token": "0x56F64C3BB45e6a248F4C783f5a1633E53D6A2371",
"Reimbursement": "0x9C5fFBFba2570A9b31D60338453C5480Ce74B342"
"Contributor": "0x95DC31665D193E377f54b70C535fcDb205525291",
"Contribution": "0x049bA8E70FEbFfd6d03C71211bDA37B4ff064115",
"Token": "0x7ab26A0f00eF0D6e05e5BDE047505a4eD53aF809",
"Reimbursement": "0x99EC72b34295b62f4bC1527Da461262c615a0b2c"
},
"1337": {
"Contributor": "0xCc66f9A3cA2670972938FAD91d0865c4a62DFB25",

View File

@ -41,6 +41,8 @@ class Contribution extends Record {
async add (contributionAttr, callOptions = {}) {
const contribution = new ContributionSerializer(contributionAttr);
const confirmedAtBlock = contributionAttr.confirmedAtBlock || 0;
const vetoed = contributionAttr.vetoed || false;
try { await contribution.validate(); }
catch (error) { return Promise.reject(error); }
@ -56,9 +58,11 @@ class Contribution extends Record {
ipfsHashAttr.hashDigest,
ipfsHashAttr.hashFunction,
ipfsHashAttr.hashSize,
confirmedAtBlock,
vetoed,
];
return this.contract.add(...contribution, 0, false, callOptions);
return this.contract.add(...contribution, callOptions);
});
}

View File

@ -52,6 +52,7 @@ class Contributor extends Record {
const jsonStr = contributor.serialize();
// console.log('Adding IPFS doc for', contributorAttr.account);
return this.ipfs
.add(jsonStr)
.then((ipfsHashAttr) => {
@ -62,7 +63,11 @@ class Contributor extends Record {
ipfsHashAttr.hashSize,
];
// console.log('Adding onchain record for', contributorAttr.account);
return this.contract.addContributor(...contributor, callOptions);
}).catch(err => {
console.log('Failed to add IPFS document:', err.message);
throw(err);
});
}

View File

@ -16,13 +16,15 @@ class Reimbursement extends Record {
}
getData (id) {
return this.contract.getReimbursement(id);
return this.contract.get(id);
}
async add (attrs, callOptions = {}) {
const amount = parseInt(attrs.amount);
const token = attrs.token;
const recipientId = attrs.recipientId;
const confirmedAtBlock = attrs.confirmedAtBlock || 0;
const vetoed = attrs.vetoed || false;
const expenses = attrs.expenses.map((e) => new ExpenseSerializer(e));
let errorMessage;
@ -56,6 +58,8 @@ class Reimbursement extends Record {
ipfsHashAttr.hashDigest,
ipfsHashAttr.hashFunction,
ipfsHashAttr.hashSize,
confirmedAtBlock,
vetoed,
];
return this.contract.add(...reimbursement, callOptions);

View File

@ -29,6 +29,7 @@ class ExpenseSerializer {
description,
currency,
amount,
amountSats,
date,
url,
tags,
@ -42,6 +43,7 @@ class ExpenseSerializer {
description,
currency,
amount,
amountSats,
date,
'tags': tags || [],
'details': details || {},
@ -76,6 +78,7 @@ class ExpenseSerializer {
description,
currency,
amount,
amountSats,
date,
url,
tags,
@ -87,6 +90,7 @@ class ExpenseSerializer {
description,
currency,
amount,
amountSats,
date,
url,
tags,

View File

@ -9,6 +9,13 @@ class IPFS {
}
this._config = config;
this._ipfsAPI = ipfsClient.create(config);
this._ipfsAPI.id().then(res => {
console.debug('IPFS ID:', res.id);
}).catch(e => {
console.debug('IPFS config:', config);
console.warn('Failed to initialize IPFS:', e.message);
});
}
async catAndMerge (contractData, deserialize) {

36
package-lock.json generated
View File

@ -1,15 +1,15 @@
{
"name": "kredits-contracts",
"version": "7.0.0",
"name": "@kredits/contracts",
"version": "7.5.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "kredits-contracts",
"version": "7.0.0",
"name": "@kredits/contracts",
"version": "7.5.0",
"license": "MIT",
"dependencies": {
"@kosmos/schemas": "^3.1.0",
"@kosmos/schemas": "^3.2.0",
"ethers": "^5.4.7",
"ipfs-http-client": "^56.0.3",
"multihashes": "^4.0.3",
@ -20,7 +20,7 @@
"@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@openzeppelin/contracts-upgradeable": "^4.3.2",
"@openzeppelin/contracts-upgradeable": "^4.8.3",
"@openzeppelin/hardhat-upgrades": "^1.10.0",
"async-each-series": "^1.1.0",
"chai": "^4.3.6",
@ -1022,9 +1022,9 @@
}
},
"node_modules/@kosmos/schemas": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@kosmos/schemas/-/schemas-3.1.0.tgz",
"integrity": "sha512-yOTK5WiXFDNAitPByMabE365aEEzFHgSUSgAssbJWt7BZ80HQSVu8XWrQiTbFbCkoIBmXwPP/RoxgXJQVgZTFQ=="
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@kosmos/schemas/-/schemas-3.2.0.tgz",
"integrity": "sha512-GyWXmWcATcakmEdPOpafdckBgWFqcpSh+tB8nm11VGgtgA94pfoFhKZ3t88WELItKfuP/GFHgMiZmdMB3bSkdQ=="
},
"node_modules/@metamask/eth-sig-util": {
"version": "4.0.1",
@ -1225,9 +1225,9 @@
}
},
"node_modules/@openzeppelin/contracts-upgradeable": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz",
"integrity": "sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==",
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.3.tgz",
"integrity": "sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg==",
"dev": true
},
"node_modules/@openzeppelin/hardhat-upgrades": {
@ -20786,9 +20786,9 @@
}
},
"@kosmos/schemas": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@kosmos/schemas/-/schemas-3.1.0.tgz",
"integrity": "sha512-yOTK5WiXFDNAitPByMabE365aEEzFHgSUSgAssbJWt7BZ80HQSVu8XWrQiTbFbCkoIBmXwPP/RoxgXJQVgZTFQ=="
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@kosmos/schemas/-/schemas-3.2.0.tgz",
"integrity": "sha512-GyWXmWcATcakmEdPOpafdckBgWFqcpSh+tB8nm11VGgtgA94pfoFhKZ3t88WELItKfuP/GFHgMiZmdMB3bSkdQ=="
},
"@metamask/eth-sig-util": {
"version": "4.0.1",
@ -20951,9 +20951,9 @@
}
},
"@openzeppelin/contracts-upgradeable": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz",
"integrity": "sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==",
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.3.tgz",
"integrity": "sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg==",
"dev": true
},
"@openzeppelin/hardhat-upgrades": {

View File

@ -1,6 +1,6 @@
{
"name": "@kredits/contracts",
"version": "7.0.0",
"version": "7.5.0",
"description": "Smart contracts and JavaScript API for Kredits",
"main": "./lib/kredits.js",
"directories": {
@ -22,11 +22,9 @@
"lint:contract-tests": "eslint apps/*/test",
"lint:wrapper": "eslint lib/",
"test": "hardhat test",
"test:token": "cd apps/token && npm run test",
"test:contributor": "cd apps/contributor && npm run test",
"test:contribution": "cd apps/contribution && npm run test",
"test:proposal": "cd apps/proposal && npm run test",
"setup-git-hooks": "sh scripts/git-hooks/install"
"setup-git-hooks": "sh scripts/git-hooks/install",
"preversion": "npm test && npm run build",
"version": "git add lib/abis"
},
"repository": {
"type": "git",
@ -42,7 +40,7 @@
"@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@openzeppelin/contracts-upgradeable": "^4.3.2",
"@openzeppelin/contracts-upgradeable": "^4.8.3",
"@openzeppelin/hardhat-upgrades": "^1.10.0",
"async-each-series": "^1.1.0",
"chai": "^4.3.6",
@ -68,7 +66,7 @@
"yargs": "^15.0.0"
},
"dependencies": {
"@kosmos/schemas": "^3.1.0",
"@kosmos/schemas": "^3.2.0",
"ethers": "^5.4.7",
"ipfs-http-client": "^56.0.3",
"multihashes": "^4.0.3",

View File

@ -36,7 +36,7 @@ async function main() {
const blocksVetoPeriod = 40320; // 7 days; 15 seconds block time
await deployContractProxy('Contributor');
await deployContractProxy('Contributor', [ '0x0000000000000000000000000000000000000000' ] );
await deployContractProxy('Contribution', [ blocksVetoPeriod ]);
await deployContractProxy('Token');
await deployContractProxy('Reimbursement');

View File

@ -1,3 +1,4 @@
const fs = require('fs');
const Kredits = require('../../lib/kredits');
async function main() {

View File

@ -0,0 +1,44 @@
const fs = require('fs');
const Kredits = require('../../lib/kredits');
async function main() {
kredits = new Kredits(hre.ethers.provider, hre.ethers.provider.getSigner())
await kredits.init();
console.log(`Using Reimbursement at: ${kredits.Reimbursement.contract.address}`);
const count = await kredits.Reimbursement.count;
const currentBlockHeight = await hre.ethers.provider.getBlockNumber();
const backup = {};
const promises = [];
for (let i = 1; i <= count; i++) {
promises.push(new Promise((resolve, reject) => {
setTimeout(async () => {
console.log(`Loading reimbursement #${i}`);
await kredits.Reimbursement.contract.get(i).then(contractData => {
backup[i] = {
recipientId: contractData.recipientId,
amount: contractData.amount,
token: contractData.token,
hashDigest: contractData.hashDigest,
hashFunction: contractData.hashFunction,
hashSize: contractData.hashSize,
confirmedAtBlock: contractData.confirmedAtBlock,
confirmed: contractData.confirmedAtBlock <= currentBlockHeight,
vetoed: contractData.vetoed,
id: contractData.id,
}
resolve();
});
}, 100 * i);
}));
}
await Promise.all(promises).then(() => {
fs.writeFileSync("./data/reimbursements.json", JSON.stringify(backup, null, 2));
console.log("Exported");
});
}
main();

View File

@ -20,7 +20,11 @@ async function main() {
const confirmationPeriod = 40320 // blocks
const unconfirmedHeight = currentBlockHeight + confirmationPeriod;
const startId = parseInt(process.env.START_AT || "0");
for (const contributionId of ids) {
if (contributionId < startId) {
continue;
}
const c = contributions[contributionId.toString()];
const confirmedAtBlock = c.confirmed ? currentBlockHeight : unconfirmedHeight;

View File

@ -0,0 +1,36 @@
const fs = require('fs');
const Kredits = require('../../lib/kredits');
async function main() {
kredits = new Kredits(hre.ethers.provider, hre.ethers.provider.getSigner())
await kredits.init();
console.log(`Using Reimbursement at: ${kredits.Reimbursement.contract.address}`);
const count = await kredits.Reimbursement.count;
console.log(`Currently ${count} entries`);
try {
const data = fs.readFileSync("./data/reimbursements.json");
const reimbursements = JSON.parse(data);
const ids = Object.keys(reimbursements)
.map(k => parseInt(k))
.sort(function(a, b) { return a - b });
for (const reimbursementId of ids) {
const reimbursement = reimbursements[reimbursementId.toString()];
const result = await kredits.Reimbursement.contract.add(
reimbursement.amount,
reimbursement.token,
reimbursement.recipientId,
reimbursement.hashDigest,
reimbursement.hashFunction,
reimbursement.hashSize,
);
console.log(`Adding reimbursement #${reimbursementId}: ${result.hash}`);
await result.wait();
};
} catch (e) {
console.error(e);
}
}
main();

View File

@ -39,7 +39,7 @@ async function main() {
contractWrapper.contract[method];
try {
// console.log('trying', func);
// console.log('trying', contractName, method, args);
const result = await func.apply(contractWrapper, args);
// console.log('result:', result);
await result.wait();

View File

@ -7,7 +7,17 @@ async function main() {
await kredits.init();
const ContributorV2 = await ethers.getContractFactory("Contributor");
const contributor = await upgrades.upgradeProxy(kredits.Contributor.address, ContributorV2);
const contributor = await upgrades.upgradeProxy(
kredits.Contributor.address,
ContributorV2,
{
call: {
fn: "reinitialize",
args: [
"0xc80d2513277FA04B10403E2D1d7dAa86F931f4d1"
]
}
});
console.log("Contributor upgraded");
console.log(`Contributor address: ${contributor.address}`);
@ -16,4 +26,4 @@ async function main() {
console.log("DONE!");
}
main();
main()

View File

@ -9,7 +9,7 @@ describe("Contribution contract", async function () {
[owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7] = await ethers.getSigners();
let accounts = [owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7];
const contributorFactory = await ethers.getContractFactory("Contributor");
Contributor = await upgrades.deployProxy(contributorFactory);
Contributor = await upgrades.deployProxy(contributorFactory, ["0x2946fFfd31096435cb0fc927D306E1C006C5D1aF"]);
for (const account of accounts) {
await Contributor.addContributor(account.address, "0x99b8afd7b266e19990924a8be9099e81054b70c36b20937228a77a5cf75723b8", 18, 32);
}
@ -67,7 +67,7 @@ describe("Contribution contract", async function () {
500, 1,
"0xe794f010e617449719c64076546254129f63a6d16cf200031afa646aeb35777f",
18, 32, 0, false
)).to.be.revertedWith("requires kredits or core status");
)).to.be.revertedWith("Requires kredits or core status");
expect(await Contribution.contributionsCount()).to.equal(0);
});
@ -76,7 +76,7 @@ describe("Contribution contract", async function () {
500, 1,
"0xe794f010e617449719c64076546254129f63a6d16cf200031afa646aeb35777f",
18, 32, 23000, true
)).to.be.revertedWith("extra arguments during migration only");
)).to.be.revertedWith("Extra arguments not allowed");
expect(await Contribution.contributionsCount()).to.equal(0);
});

View File

@ -1,14 +1,14 @@
const { expect } = require("chai");
const { ethers, upgrades } = require("hardhat");
let owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7;
let owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7, addr8;
let Contribution, Contributor, Token;
describe("Contributor contract", async function () {
before(async function () {
[owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7] = await ethers.getSigners();
[owner, addr1, addr2, addr3, addr4, addr5, addr6, addr7, addr8] = await ethers.getSigners();
const contributorFactory = await ethers.getContractFactory("Contributor");
Contributor = await upgrades.deployProxy(contributorFactory);
Contributor = await upgrades.deployProxy(contributorFactory, [addr8.address]);
const contributionFactory = await ethers.getContractFactory("Contribution");
Contribution = await upgrades.deployProxy(contributionFactory, [40321]);
const tokenFactory = await ethers.getContractFactory("Token");
@ -30,6 +30,10 @@ describe("Contributor contract", async function () {
expect(await Contributor.deployer()).to.equal(owner.address);
expect(await Contributor.deployer()).to.not.equal(addr1.address);
});
it("sets a profile manager address", async function () {
expect(await Contributor.profileManager()).to.equal(addr8.address);
});
});
describe("add()", function () {
@ -38,7 +42,7 @@ describe("Contributor contract", async function () {
"0x608FD4b95116Ea616990Aaeb1d4f1ce07612f261",
"0x1d9de6de5c72eedca6d7a5e8a9159e2f5fe676506aece3000acefcc821723429",
18, 32
)).to.be.revertedWith("Core only");
)).to.be.revertedWith("Only core and profile manager");
expect(await Contributor.contributorsCount()).to.equal(8);
});
@ -70,6 +74,18 @@ describe("Contributor contract", async function () {
18, 32
)).to.emit(Contributor, "ContributorAdded").withArgs(10, "0x765E88b4F9a59C3a3b300C6eFF9E6E9fDDf9FbD9");
});
it("allows the profile manager account to create a contributor profile", async function () {
await Contributor.connect(addr8).addContributor(
"0x954712B8703Df5255A219B139ba7BFC256E72a15",
"0x1d9de6de5c72eedca6d7a5e8a9159e2f5fe676506aece3000acefcc821723429",
18, 32
);
expect(await Contributor.contributorsCount()).to.equal(11);
const c = await Contributor.getContributorById(11);
expect(c['account']).to.equal("0x954712B8703Df5255A219B139ba7BFC256E72a15");
});
});
describe("withdraw()", function () {