Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ get_assets(env, user) -> Vec<AssetInfo>

// Spend limits
set_spend_limit(env, user, asset_code, limit: i128) -> Result<()>
propose_spend_limit_increase(env, user, asset_code, limit: i128, delay_in_ledgers: u32) -> Result<()>
execute_spend_limit_increase(env, user, asset_code) -> Result<()>
cancel_spend_limit_increase(env, user, asset_code) -> Result<()>
get_spend_limit_proposal(env, user, asset_code) -> Option<SpendLimitProposal>
get_spend_limit(env, user, asset_code) -> i128
record_spend(env, user, asset_code, amount) -> Result<()>
```
Expand All @@ -80,6 +84,9 @@ record_spend(env, user, asset_code, amount) -> Result<()>

- Limit is per-user, per-asset, daily (86 400-second window from ledger timestamp).
- `limit = 0` means unlimited.
- **Asymmetric Limit Modifications & Compromised-Key Defense:**
- Lowering an existing limit or establishing an initial cap is applied **instantly** via `set_spend_limit` (with retroactive enforcement ensuring today's spend doesn't already exceed the new cap).
- Raising an existing limit or removing an active cap (`limit = 0`) cannot be done instantly via `set_spend_limit` (rejected with `SpendLimitIncreaseRequiresProposal`). It requires proposing the increase with a minimum timelock delay (`MIN_SPEND_LIMIT_INCREASE_DELAY = 17_280` ledgers / ~24 hours) via `propose_spend_limit_increase`, waiting for the timelock window, and calling `execute_spend_limit_increase`. This defends against the compromised-key threat model by ensuring an attacker with valid user signatures cannot raise the limit and drain funds in a single transaction or session without giving the owner time to cancel (`cancel_spend_limit_increase`).
- `record_spend` is called from any payment path; rejects with `SpendLimitExceeded` if
cumulative daily spend would exceed the limit.
- Day window resets automatically — no manual reset required.
Expand Down
467 changes: 455 additions & 12 deletions contracts/globe-wallet/src/lib.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
},
"ext": "v0"
},
4095
518400
]
],
[
Expand Down Expand Up @@ -151,7 +151,7 @@
},
"ext": "v0"
},
4095
518400
]
]
]
Expand Down Expand Up @@ -348,7 +348,7 @@
],
"data": {
"error": {
"contract": 3
"contract": 1003
}
}
}
Expand All @@ -369,7 +369,7 @@
},
{
"error": {
"contract": 3
"contract": 1003
}
}
],
Expand All @@ -394,7 +394,7 @@
},
{
"error": {
"contract": 3
"contract": 1003
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
},
"ext": "v0"
},
4095
518400
]
],
[
Expand Down Expand Up @@ -306,7 +306,7 @@
},
"ext": "v0"
},
4095
518400
]
]
]
Expand Down Expand Up @@ -662,4 +662,4 @@
"failed_call": false
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,43 @@
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4"
}
},
{
"key": {
"vec": [
{
"symbol": "GuardianMembership"
}
]
},
"val": {
"map": [
{
"key": {
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M"
},
"val": {
"bool": true
}
},
{
"key": {
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4"
},
"val": {
"bool": true
}
},
{
"key": {
"address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM"
},
"val": {
"bool": true
}
}
]
}
},
{
"key": {
"vec": [
Expand Down Expand Up @@ -147,7 +184,7 @@
},
"ext": "v0"
},
4095
518400
]
],
[
Expand Down Expand Up @@ -267,7 +304,7 @@
},
"ext": "v0"
},
4095
518400
]
]
]
Expand Down
Loading