66 "encoding/hex"
77 "fmt"
88 "strconv"
9+ "time"
10+
11+ "cosmossdk.io/math"
912
1013 sdk "github.com/cosmos/cosmos-sdk/types"
1114 skeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
@@ -23,6 +26,10 @@ func (k Keeper) ProcessDeposit(ctx context.Context, ev *bindings.IPTokenStakingD
2326 sdkCtx := sdk .UnwrapSDKContext (ctx )
2427 cachedCtx , writeCache := sdkCtx .CacheContext ()
2528
29+ var isRefund bool
30+ var refundAmount math.Int
31+ var completionTime time.Time
32+
2633 defer func () {
2734 if r := recover (); r != nil {
2835 err = errors .WrapErrWithCode (errors .UnexpectedCondition , fmt .Errorf ("panic caused by %v" , r ))
@@ -41,18 +48,27 @@ func (k Keeper) ProcessDeposit(ctx context.Context, ev *bindings.IPTokenStakingD
4148 )
4249 }
4350
44- sdkCtx .EventManager ().EmitEvents (sdk.Events {
45- e .AppendAttributes (
46- sdk .NewAttribute (types .AttributeKeyAmount , ev .StakeAmount .String ()),
47- sdk .NewAttribute (types .AttributeKeyBlockHeight , strconv .FormatInt (sdkCtx .BlockHeight (), 10 )),
48- sdk .NewAttribute (types .AttributeKeyDelegatorAddress , ev .Delegator .String ()),
49- sdk .NewAttribute (types .AttributeKeyValidatorCmpPubKey , hex .EncodeToString (ev .ValidatorCmpPubkey )),
50- sdk .NewAttribute (types .AttributeKeyDelegateID , ev .DelegationId .String ()),
51- sdk .NewAttribute (types .AttributeKeyPeriodType , strconv .FormatInt (ev .StakingPeriod .Int64 (), 10 )),
52- sdk .NewAttribute (types .AttributeKeySenderAddress , ev .OperatorAddress .Hex ()),
53- sdk .NewAttribute (types .AttributeKeyTxHash , hex .EncodeToString (ev .Raw .TxHash .Bytes ())),
54- ),
55- })
51+ e = e .AppendAttributes (
52+ sdk .NewAttribute (types .AttributeKeyAmount , ev .StakeAmount .String ()),
53+ sdk .NewAttribute (types .AttributeKeyBlockHeight , strconv .FormatInt (sdkCtx .BlockHeight (), 10 )),
54+ sdk .NewAttribute (types .AttributeKeyDelegatorAddress , ev .Delegator .String ()),
55+ sdk .NewAttribute (types .AttributeKeyValidatorCmpPubKey , hex .EncodeToString (ev .ValidatorCmpPubkey )),
56+ sdk .NewAttribute (types .AttributeKeyDelegateID , ev .DelegationId .String ()),
57+ sdk .NewAttribute (types .AttributeKeyPeriodType , strconv .FormatInt (ev .StakingPeriod .Int64 (), 10 )),
58+ sdk .NewAttribute (types .AttributeKeySenderAddress , ev .OperatorAddress .Hex ()),
59+ sdk .NewAttribute (types .AttributeKeyTxHash , hex .EncodeToString (ev .Raw .TxHash .Bytes ())),
60+ sdk .NewAttribute (types .AttributeKeyIsRefund , strconv .FormatBool (isRefund )),
61+ )
62+
63+ // if it's a refund, add refund attributes
64+ if isRefund {
65+ e = e .AppendAttributes (
66+ sdk .NewAttribute (types .AttributeKeyRefundAmount , refundAmount .String ()),
67+ sdk .NewAttribute (types .AttributeKeyRefundCompletionTime , completionTime .String ()),
68+ )
69+ }
70+
71+ sdkCtx .EventManager ().EmitEvents (sdk.Events {e })
5672 }()
5773
5874 validatorPubkey , err := k1util .PubKeyBytesToCosmos (ev .ValidatorCmpPubkey )
@@ -96,8 +112,19 @@ func (k Keeper) ProcessDeposit(ctx context.Context, ev *bindings.IPTokenStakingD
96112 }
97113
98114 val , err := k .stakingKeeper .GetValidator (cachedCtx , validatorAddr )
115+
99116 if errors .Is (err , stypes .ErrNoValidatorFound ) {
100- return errors .WrapErrWithCode (errors .ValidatorNotFound , err )
117+ isRefund = true
118+ log .Info (cachedCtx , "Validator not found, refunding deposit minus the refund fee" ,
119+ "val_addr" , validatorAddr ,
120+ "val_evm_addr" , valEvmAddr .String (),
121+ "del_addr" , depositorAddr .String (),
122+ "del_evm_addr" , ev .Delegator .String (),
123+ )
124+
125+ refundAmount , completionTime , err = k .RefundDelegation (ctx , depositorAddr , validatorAddr , amountCoin )
126+
127+ return err // skip delegation logic
101128 } else if err != nil {
102129 return errors .Wrap (err , "get validator failed" )
103130 }
@@ -115,11 +142,6 @@ func (k Keeper) ProcessDeposit(ctx context.Context, ev *bindings.IPTokenStakingD
115142 delID = stypes .FlexiblePeriodDelegationID
116143 }
117144
118- evmstakingSKeeper , ok := k .stakingKeeper .(* skeeper.Keeper )
119- if ! ok {
120- return errors .New ("type assertion failed" )
121- }
122-
123145 // Note that, after minting, we save the mapping between delegator bech32 address and evm address, which will be used in the withdrawal queue.
124146 // The saving is done regardless of any error below, as the money is already minted and sent to the delegator, who can withdraw the minted amount.
125147 // NOTE: Do not overwrite the existing withdraw/reward address set by the delegator.
@@ -146,13 +168,25 @@ func (k Keeper) ProcessDeposit(ctx context.Context, ev *bindings.IPTokenStakingD
146168 return errors .Wrap (err , "create stake coin for depositor: send coins" )
147169 }
148170
171+ return k .CreateDelegation (cachedCtx , validatorAddr .String (), depositorAddr .String (), amountCoin , delID , periodType )
172+ }
173+
174+ func (k Keeper ) CreateDelegation (
175+ cachedCtx context.Context , validatorAddr , depositorAddr string , amountCoin sdk.Coin , periodDelegationID string ,
176+ periodType int32 ,
177+ ) error {
178+ evmstakingSKeeper , ok := k .stakingKeeper .(* skeeper.Keeper )
179+ if ! ok {
180+ return errors .New ("type assertion failed" )
181+ }
182+
149183 skeeperMsgServer := skeeper .NewMsgServerImpl (evmstakingSKeeper )
150184 // Delegation by the depositor on the validator (validator existence is checked in msgServer.Delegate)
151185 msg := stypes .NewMsgDelegate (
152- depositorAddr . String () , validatorAddr . String () , amountCoin ,
153- delID , periodType ,
186+ depositorAddr , validatorAddr , amountCoin ,
187+ periodDelegationID , periodType ,
154188 )
155- if _ , err = skeeperMsgServer .Delegate (cachedCtx , msg ); errors .Is (err , stypes .ErrDelegationBelowMinimum ) {
189+ if _ , err : = skeeperMsgServer .Delegate (cachedCtx , msg ); errors .Is (err , stypes .ErrDelegationBelowMinimum ) {
156190 return errors .WrapErrWithCode (errors .InvalidDelegationAmount , err )
157191 } else if errors .Is (err , stypes .ErrNoPeriodTypeFound ) {
158192 return errors .WrapErrWithCode (errors .InvalidPeriodType , err )
@@ -166,3 +200,52 @@ func (k Keeper) ProcessDeposit(ctx context.Context, ev *bindings.IPTokenStakingD
166200func (k Keeper ) ParseDepositLog (ethlog ethtypes.Log ) (* bindings.IPTokenStakingDeposit , error ) {
167201 return k .ipTokenStakingContract .ParseDeposit (ethlog )
168202}
203+
204+ func (k Keeper ) RefundDelegation (
205+ ctx context.Context , delegatorAddr sdk.AccAddress , validatorAddr sdk.ValAddress , rawRefundAmountCoin sdk.Coin ,
206+ ) (refundAmount math.Int , completionTime time.Time , err error ) {
207+ sdkCtx := sdk .UnwrapSDKContext (ctx )
208+
209+ // the min refund fee amount will be `refundFeeBps * minDelegationAmount (1024) / 10_000bps`
210+ refundFeeBps , err := k .RefundFeeBps (ctx )
211+ if err != nil {
212+ return math.Int {}, time.Time {}, errors .Wrap (err , "get refund fee" )
213+ }
214+ refundFeeAmount := rawRefundAmountCoin .Amount .Mul (math .NewInt (int64 (refundFeeBps ))).Quo (math .NewInt (10_000 ))
215+ refundAmount = rawRefundAmountCoin .Amount .Sub (refundFeeAmount )
216+
217+ refundPeriod , err := k .RefundPeriod (ctx )
218+ if err != nil {
219+ return math.Int {}, time.Time {}, errors .Wrap (err , "get refund period" )
220+ }
221+
222+ completionTime = sdkCtx .BlockTime ().Add (refundPeriod )
223+
224+ // set ubd index in mapping (needed before inserting to ubd queue)
225+ ubd , err := k .stakingKeeper .SetUnbondingDelegationEntry (
226+ ctx ,
227+ delegatorAddr ,
228+ validatorAddr ,
229+ sdkCtx .BlockHeight (),
230+ completionTime ,
231+ refundAmount ,
232+ )
233+ if err != nil {
234+ return math.Int {}, time.Time {}, errors .Wrap (err , "set unbonding delegation entry" )
235+ }
236+
237+ // push the refund to the unbonding queue
238+ err = k .stakingKeeper .InsertUBDQueue (ctx , ubd , completionTime )
239+ if err != nil {
240+ return math.Int {}, time.Time {}, errors .Wrap (err , "insert unbonding delegation queue" )
241+ }
242+
243+ log .Debug (ctx , "Added refund to unbonding queue" ,
244+ "del_addr" , delegatorAddr .String (),
245+ "val_addr" , validatorAddr .String (),
246+ "amount" , refundAmount .String (),
247+ "completion_time" , completionTime ,
248+ )
249+
250+ return refundAmount , completionTime , nil
251+ }
0 commit comments