Cip 0105 main#1
Conversation
| calculateAvailableWithdrawAmount currentDateTime VestedAmulet{..} = let | ||
| totalVestedAmulet : Decimal = castAndRound $ aggregateLockedAmulet.amount.initialAmount + withdrawnAmount | ||
| in if currentDateTime >= endDate | ||
| then (castAndRound totalVestedAmulet) - withdrawnAmount |
There was a problem hiding this comment.
nit: you are already used castAndRound on line 24, so this does nothing.
Also on line 24 you include the withdrawnAmount in the castAndRound, while here (and on line 31) it is excluded, is this intentional and why ? ( i assume some rounding errors could occur)
|
|
||
| template VestedAmulet | ||
| with | ||
| aggregateLockedAmulet : Amulet |
There was a problem hiding this comment.
| aggregateLockedAmulet : Amulet | |
| VestingLockedAmulet: Amulet |
nit: to keep naming consistent and seperate from the agrgrgateLockedAmulet
| -- one under their control. | ||
| controller authorizers | ||
| do | ||
| flip require (authorizers `elem` unlockControllerSets) $ |
There was a problem hiding this comment.
nit: we technical here have the same minor issues as i mentioned for Jonathan.
authorizers [Bob,Alice] against unlockControllerSets [Alice,Bob] will fail (even though they contain the same elements)
| (currentEligibleWithdrawableAmount > 0.0) | ||
|
|
||
| -- Amulet for Unlocked Amount of CC | ||
| unlockedAmulet <- create Amulet with |
There was a problem hiding this comment.
| unlockedAmulet <- create Amulet with | |
| unlockedAmuletCid <- create Amulet with |
nit: (to keep naming consistent with amulet approach)
| let remainingAggregateLockedAmount = aggregateLockedAmulet.amount.initialAmount - currentEligibleWithdrawableAmount | ||
|
|
||
| -- Vested Amulet in case any amount remains locked in aggregateLockedAmulet | ||
| vestedAmulet <- if remainingAggregateLockedAmount > 0.0 then do |
There was a problem hiding this comment.
| vestedAmulet <- if remainingAggregateLockedAmount > 0.0 then do | |
| vestedAmuletCid <- if remainingAggregateLockedAmount > 0.0 then do |
nit: (to keep naming consistent with amulet approach)
| choice VestedAmulet_WithdrawAvailableUnlockedAmulet : VestedAmulet_WithdrawResult | ||
| with | ||
| authorizers : [Party] | ||
| openRound : Round |
There was a problem hiding this comment.
this is never validated if it is actually open.
you probably need something like:
round <- fetchReferenceData (ForDso dso) openMiningRoundCid
require ("mining round is open: " <> show round) (round.opensAt <= now)
this would only work however if the authorizers contains DSO, eles you would have to do something like:
change to ContractId OpenMiningRound instead of round
and then use:
fetchPublicReferenceData (ForDso with dso = expectedDso) openRoundCid (OpenMiningRound_Fetch fetchAs ...)
if going with the second approach we also need to validate that openRound.dso == expectedDso
| withdrawnAmount : Decimal | ||
| unlockControllerSets : ControllerSets | ||
| where | ||
| signatory aggregateLockedAmulet.dso, aggregateLockedAmulet.owner |
There was a problem hiding this comment.
i would probably add an ensure here, with checks like:
validExpiringAmount aggregateLockedAmulet.amount
startDate < endDate
withdrawnAmount >= 0.0
| deriving (Show, Eq) | ||
|
|
||
| calculateAvailableWithdrawAmount : Time -> VestedAmulet -> Decimal | ||
| calculateAvailableWithdrawAmount currentDateTime VestedAmulet{..} = let |
There was a problem hiding this comment.
i would probably add some max 0.0 {returnValue} on the two places you return, just to safeguard against transient negatives
| (currentEligibleWithdrawableAmount > 0.0) | ||
|
|
||
| -- Amulet for Unlocked Amount of CC | ||
| unlockedAmulet <- create Amulet with |
There was a problem hiding this comment.
instead of create Amulet i would suggest to create a new non-consuming choice in amulet rules like AmuletRules_VestingWithdrawMint and then add amuletRulesCid as a argument on the class. allow you to easily use existing helpers to validate and add things like meta data etc.
pseudo example snippet:
nonconsuming choice AmuletRules_VestingWithdrawMint : AmuletRules_VestingWithdrawMintResult
with
owner : Party
amount : Decimal
openRoundCid : ContractId OpenMiningRound
expectedDso : Optional Party
controller dso
do
checkExpectedDso dso expectedDso
require "amount > 0" (amount > 0.0)
openRound <- fetchReferenceData (ForDso with dso) openRoundCid
now <- getTime
require "round is open" (openRound.opensAt <= now)
let cfg = transferConfigAmuletFromOpenRound openRound
amuletCid <- create Amulet with
dso
owner
amount = expiringAmount cfg.holdingFee amount openRound.round
return AmuletRules_VestingWithdrawMintResult with
amuletCid
meta = Some (simpleHoldingTxMeta TxKind_Unlock (Some "vesting withdraw") None)
| , "'." | ||
| ] | ||
|
|
||
| flip require ((show aggregateLockedAmulet.dso) == (show expectedDso)) $ |
There was a problem hiding this comment.
remove the show from the comparison, this weakens it (you can look at checkExpectedDso for inspiration)
Pull Request Checklist
Cluster Testing
/cluster_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./upgrade_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./hdm_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./lsu_teston this PR to request it, and ping someone with access to the DA-internal system to approve it.PR Guidelines
Fixes #n, and mention issues worked on using#nMerge Guidelines