Skip to content

Commit

Permalink
Safe wallet (#243)
Browse files Browse the repository at this point in the history
* [safe wallet] update safe wallet lock

* [safe wallet] update safe wallet definition

* [safe wallet] update safe wallet definition

* [safe wallet] update safe wallet definition

* [safe wallet] update multiSig comments
  • Loading branch information
mike-diamond authored Jan 30, 2025
1 parent 5bf8ab9 commit 6a0af51
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 34 deletions.
30 changes: 24 additions & 6 deletions src/methods/boost/transactions/lock/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ZeroAddress } from 'ethers'
import { MaxUint256, ZeroAddress } from 'ethers'

import type { LockInput } from './types'
import { validateArgs } from '../../../../utils'
Expand All @@ -14,12 +14,19 @@ type CommonLogicInput = LockInput & {
export const commonLogic = async (values: CommonLogicInput) => {
const {
contracts, options, provider, amount, vaultAddress, userAddress, referrerAddress = ZeroAddress,
permitParams, mockPermitSignature,
mockPermitSignature,
} = values

validateArgs.bigint({ amount })
validateArgs.address({ vaultAddress, userAddress, referrerAddress })

const code = await provider.getCode(userAddress)
const isMultiSig = code !== '0x'

let multiSigData = null

const permitParams = isMultiSig ? null : values.permitParams

if (permitParams) {
validateArgs.object({ permitParams })

Expand Down Expand Up @@ -66,7 +73,15 @@ export const commonLogic = async (values: CommonLogicInput) => {
const isPermitRequired = allowance < amount

if (isPermitRequired) {
if (mockPermitSignature) {
// It is hard to make permit action for MultiSig e.g. Safe wallet,
// so we need to use approve instead
if (isMultiSig) {
multiSigData = {
contract: contracts.tokens.mintToken,
approveArgs: [ strategyProxy, MaxUint256 ] as [ string, bigint ],
}
}
else if (mockPermitSignature) {
params.push({
method: 'permit',
args: [
Expand Down Expand Up @@ -105,9 +120,12 @@ export const commonLogic = async (values: CommonLogicInput) => {
})

return {
...multicallArgs,
request: {
params,
multiSigData,
multicallArgs: {
...multicallArgs,
request: {
params,
},
},
}
}
13 changes: 12 additions & 1 deletion src/methods/boost/transactions/lock/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ import { boostMulticall } from '../../../../contracts'


const lock: Lock = async (values) => {
const multicallArgs = await commonLogic(values)
const { provider, userAddress } = values

const { multiSigData, multicallArgs } = await commonLogic(values)

if (multiSigData) {
const signer = await provider.getSigner(userAddress)
const signedContract = multiSigData.contract.connect(signer)

const { hash } = await signedContract.approve(...multiSigData.approveArgs)

await provider.waitForTransaction(hash)
}

const result = await boostMulticall<{ hash: string }>(multicallArgs)

Expand Down
21 changes: 12 additions & 9 deletions src/methods/boost/transactions/lock/lock.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ Boost your osToken apy using leverage staking

#### Arguments:

| Name | Type | Required | Description |
|-----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| amount | `bigint` | **Yes** | Boost amount |
| userAddress | `string` | **Yes** | The user address |
| vaultAddress | `string` | **Yes** | The address of the vault that will mint osTokens for leverage staking |
| boostAddress | `string` | **Yes** | The address of the strategy proxy (TODO method) |
| referrerAddress | `string` | **No** | The address of the referrer |
| permitParams | `PermitParams` | **No** | The permit signature it is required only if there is not enough osToken allowance for the strategy proxy contract. It will be obtained automatically using the [utils.getPermitSignature](/utils/getpermitsignature) method |
| Name | Type | Required | Description |
|-----------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| amount | `bigint` | **Yes** | Boost amount |
| userAddress | `string` | **Yes** | The user address |
| vaultAddress | `string` | **Yes** | The address of the vault that will mint osTokens for leverage staking |
| boostAddress | `string` | **Yes** | The address of the strategy proxy using the [sdk.boost.getLeverageStrategyProxy](/boost/requests/getleveragestrategyproxy) method |
| referrerAddress | `string` | **No** | The address of the referrer |
| permitParams | `PermitParams` | **No** | The permit signature is required if there isn’t enough osToken allowance for the strategy proxy contract.<br /><br />**For MultiSig**<br />The permit signature is not necessary for Multi Sig (e.g. Safe Wallet), as it should use `sdk.contracts.mintToken.approve(boostAddress, MaxUint256)` instead of a permit call to set up osToken allowance. This will be called in the action if needed.<br /><br />**For other wallets**<br />The permit signature is optional since it will be obtained automatically using the [utils.getPermitSignature](/utils/getpermitsignature) method. |

```ts
type PermitParams = {
Expand All @@ -42,7 +42,10 @@ const params = {
// Send transaction
const hash = await sdk.boost.lock(params)
// When you sign transactions on the backend (for custodians)
const { data, to, value } = await sdk.boost.lock.encode(params)
// `lockTxData` will always be returned, while `approveTxData` will only be returned for MultiSig e.g. Safe Wallet
// if there isn’t enough osToken allowance, otherwise it will be null
const { lockTxData, approveTxData } = await sdk.boost.lock.encode(params)

// Get an approximate gas per transaction
const gas = await sdk.boost.lock.estimateGas(params)
```
33 changes: 24 additions & 9 deletions src/methods/boost/transactions/lock/lockEncode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,31 @@ import { commonLogic } from './common'
import { boostMulticall } from '../../../../contracts'


const lockEncode = async (values: LockInput): Promise<StakeWise.TransactionData> => {
const multicallArgs = await commonLogic(values)
type Output = {
lockTxData: StakeWise.TransactionData
approveTxData: StakeWise.TransactionData | null
}

const lockEncode = async (values: LockInput): Promise<Output> => {
const { multiSigData, multicallArgs } = await commonLogic(values)

const [ lockTxData, approveTxData ] = await Promise.all([
boostMulticall<{ data: string, to: string }>({
...multicallArgs,
request: {
...multicallArgs.request,
transactionData: true,
},
}),
multiSigData
? multiSigData.contract.approve.populateTransaction(...multiSigData.approveArgs)
: Promise.resolve(null),
])

return boostMulticall<{ data: string, to: string }>({
...multicallArgs,
request: {
...multicallArgs.request,
transactionData: true,
},
})
return {
lockTxData,
approveTxData,
}
}


Expand Down
27 changes: 18 additions & 9 deletions src/methods/boost/transactions/lock/lockGas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@ import { boostMulticall } from '../../../../contracts'


const lockGas = async (values: LockInput) => {
const { provider } = values
const { provider, userAddress } = values

const multicallArgs = await commonLogic({ ...values, mockPermitSignature: true })
const { multiSigData, multicallArgs } = await commonLogic({ ...values, mockPermitSignature: true })

const estimatedGas = await boostMulticall<bigint>({
...multicallArgs,
request: {
...multicallArgs.request,
estimateGas: true,
},
})
const [ estimatedGasMulticall, estimatedGasApprove ] = await Promise.all([
boostMulticall<bigint>({
...multicallArgs,
request: {
...multicallArgs.request,
estimateGas: true,
},
}),
multiSigData
? multiSigData.contract.approve.estimateGas(...multiSigData.approveArgs, {
from: userAddress,
})
: Promise.resolve(0n),
])

const estimatedGas = estimatedGasMulticall + estimatedGasApprove

return getGas({ estimatedGas, provider })
}
Expand Down

0 comments on commit 6a0af51

Please sign in to comment.