Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Fix USDT payment #4306

Closed
wants to merge 17 commits into from
Closed
16 changes: 10 additions & 6 deletions dapps/marketplace/src/components/WithPrices.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import floor from 'lodash/floor'

import supportedTokens from '@origin/graphql/src/utils/supportedTokens'

// web3.utils.toWei only accepts up to 18 decimal places
function removeExtraDecimals(numStr) {
return numStr.replace(/^([0-9]+\.[0-9]{18}).*/, '$1')
}
import getUnitTokenValue from '@origin/graphql/src/utils/unitTokenValue'

/**
* Given a list of tokens and a price, returns an object with information on
Expand Down Expand Up @@ -131,12 +128,19 @@ const WithPrices = ({
}
}

if (!suggestedToken) {
// Let's default to something
suggestedToken = listing.acceptedTokens[0].id
}

return children({ prices: wallet, tokenStatus, suggestedToken })
}

function tokenStatusFor(target, wallet, proxy) {
const targetWei = removeExtraDecimals(get(wallet, `${target}.amount`) || '0')
const targetValue = web3.utils.toBN(web3.utils.toWei(targetWei, 'ether'))
const targetValue = getUnitTokenValue(
get(wallet, `${target}.amount`) || '0',
target
)

const walletBalance = get(wallet, `${target}.currency.balance`) || '0'
const availableBalance = web3.utils.toBN(walletBalance)
Expand Down
2 changes: 1 addition & 1 deletion dapps/marketplace/src/pages/listing/PaymentMethods.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const PaymentAmountRaw = ({
}
}, [paymentMethod, token])

if (!tokenObj || tokenObj.loading) {
if (tokenStatus.loading || !tokenObj) {
return (
<div className="actions">
<button className="btn btn-primary btn-rounded" disabled={true}>
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/build/contracts_rinkeby.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
"IdentityProxyImplementation": "0x8ACcCe67F87508814e79f3970F58c5D0cd31CacB",
"OGN": "0xa115e16ef6e217f7a327a57031f75ce0487aadb8",
"DAI": "0x2448eE2641d78CC42D7AD76498917359D961A783",
"USDT": "0xfb1d709cb959ac0ea14cad0927eabc7832e65058"
"USDT": "0xd2e491c652b9eff6b4dbdc0cb041c7ad2242630b"
}
2 changes: 1 addition & 1 deletion packages/graphql/fixtures/populate.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ export default async function populate(gqlClient, log, done) {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18',
decimals: '6',
supply: '3000000000'
})
log(`Deployed Tether to ${USDT.contractAddress}`)
Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ if (addresses.USDT) {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
})
}

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/localhost.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ if (addresses.USDT) {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
})
}

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/localsecure.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ if (addresses.USDT) {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
})
}

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/mainnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export default {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
}
],
DaiExchange: addresses.UniswapDaiExchange,
Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/origin.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
}
],

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/rinkeby.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
}
],

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ if (addresses.USDT) {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
})
}

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/src/configs/truffle.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ if (addresses.USDT) {
type: 'Standard',
name: 'Tether',
symbol: 'USDT',
decimals: '18'
decimals: '6'
})
}

Expand Down
3 changes: 2 additions & 1 deletion packages/graphql/src/mutations/token/deployToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import OriginToken from '@origin/contracts/build/contracts/OriginToken'
import StandardToken from '@origin/contracts/build/contracts/TestToken'
import contracts from '../../contracts'
import txHelper, { checkMetaMask } from '../_txHelper'
import getUnitTokenValue from '../../utils/unitTokenValue'

async function deployToken(_, { type, name, decimals, supply, symbol, from }) {
const web3 = contracts.web3Exec
await checkMetaMask(from)
const supplyWei = web3.utils.toWei(supply, 'ether')
const supplyWei = getUnitTokenValue(supply, parseInt(decimals))
let tx, Contract

if (type === 'Standard') {
Expand Down
3 changes: 2 additions & 1 deletion packages/graphql/src/mutations/token/transferToken.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import txHelper, { checkMetaMask } from '../_txHelper'
import contracts from '../../contracts'
import getUnitTokenValue from '../../utils/unitTokenValue'

async function transferToken(_, { token, from, to, value }) {
const contract = contracts.tokens.find(
Expand All @@ -10,7 +11,7 @@ async function transferToken(_, { token, from, to, value }) {
console.log(token, 'not found')
return
}
value = contracts.web3.utils.toWei(value, 'ether')
value = getUnitTokenValue(value, token)
const tx = contract.methods.transfer(to, value)
return txHelper({ tx, from, mutation: 'transferToken', gas: 4612388 })
}
Expand Down
5 changes: 4 additions & 1 deletion packages/graphql/src/mutations/token/updateTokenAllowance.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import txHelper, { checkMetaMask } from '../_txHelper'
import contracts from '../../contracts'

import getUnitTokenValue from '../../utils/unitTokenValue'

import createDebug from 'debug'
const debug = createDebug('origin:updateTokenAllowance:')

Expand All @@ -17,7 +20,7 @@ async function updateTokenAllowance(_, { token, from, to, value }) {
}

await checkMetaMask(from)
value = contracts.web3.utils.toWei(value, 'ether')
value = getUnitTokenValue(value, token)
const tx = tokenContract.contractExec.methods.approve(to, value)
const gas = await tx.estimateGas({ from })
debug({ token, from, to, value })
Expand Down
77 changes: 77 additions & 0 deletions packages/graphql/src/utils/unitTokenValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import memoize from 'lodash/memoize'
import contracts from '../contracts'
import currencies from './currencies'

/**
* Get the ether unit that has a certain number of decimals
*
* Ref: https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#id88
*
* @param {Number} decimals number of decimals
*
* @returns {String} the ether unit that has `decimals` decimals
*/
const getUnitWithDecimals = memoize(decimals => {
const web3 = contracts.web3

const unit = Object.keys(web3.utils.unitMap).find(unit => {
const valueInWei = web3.utils.unitMap[unit]

const zeroCount = valueInWei.length - valueInWei.replace(/0/g, '').length

return zeroCount === decimals
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT web3 units for each zero count don't exist. Sometimes there are 3 zeros between the 2 closest units. So the above function might miss the correct unit in case its' decimal count is between 2 units. (for example between szabo -> 12 zeros and nano -> 9 zeros)

Maybe one suggestion as how to amend the above implementation:

let biggestUnit = 'wei'
let c = 0
const unit = Object.keys(web3.utils.unitMap).forEach(unit => {
    const valueInWei = web3.utils.unitMap[unit]

    const zeroCount = valueInWei.length - valueInWei.replace(/0/g, '').length
    if (zeroCount <= decimals && zeroCount > biggestUnitZeros) {
        biggestUnit = unit
        biggestUnitZeros = zeroCount
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this @sparrowDom, Will fix this

})

return unit
})

/**
* Truncates the big numbers upto `n` decimals
*
* @param {String} numStr The big number as string
* @param {Number} decimals Number of decimals to truncate to
*
* @return {String} truncated number as string
*/
function removeExtraDecimals(numStr, decimals) {
return numStr.replace(
new RegExp(`^([0-9]+\\.[0-9]{${decimals || 18}}).*`),
'$1'
)
}

/**
* Takes in a token value with decimals and returns the token's value
* with the smallest unit possible without any decimals
*
* @param {String} amount The token value with decimals
* @param {String|Number} token The token ID or the number of decimals
*
* @returns {String} `amount` represented in smallest unit of `token`
*/
function getUnitTokenValue(amount, tokenOrDecimals) {
const web3 = contracts.web3

let tokenDecimals = tokenOrDecimals

if (typeof tokenOrDecimals === 'string') {
const tokenObj = currencies.data[tokenOrDecimals]

if (!tokenObj) {
// Fallback
return web3.utils.toWei(removeExtraDecimals(amount, 18), 'ether')
}

tokenDecimals = tokenObj.decimals
}

const targetWei = removeExtraDecimals(amount, tokenDecimals)

const targetUnit = getUnitWithDecimals(tokenDecimals)

const targetValue = web3.utils.toBN(web3.utils.toWei(targetWei, targetUnit))

return targetValue
}

export default getUnitTokenValue