@@ -13,6 +13,7 @@ import type { ClockMode } from './set-clock-mode';
1313import { clockModeDefault , setClockMode } from './set-clock-mode' ;
1414import { supportsInterface } from './common-functions' ;
1515import { OptionsError } from './error' ;
16+ import { toUint256 , UINT256_MAX } from './utils/convert-strings' ;
1617
1718export const crossChainBridgingOptions = [ false , 'custom' , 'superchain' ] as const ;
1819export type CrossChainBridging = ( typeof crossChainBridgingOptions ) [ number ] ;
@@ -163,6 +164,14 @@ export function isValidChainId(str: string): boolean {
163164 return chainIdPattern . test ( str ) ;
164165}
165166
167+ function scaleByPowerOfTen ( base : bigint , exponent : number ) : bigint {
168+ if ( exponent < 0 ) {
169+ return base / BigInt ( 10 ) ** BigInt ( - exponent ) ;
170+ } else {
171+ return base * BigInt ( 10 ) ** BigInt ( exponent ) ;
172+ }
173+ }
174+
166175function addPremint (
167176 c : ContractBuilder ,
168177 amount : string ,
@@ -181,6 +190,9 @@ function addPremint(
181190 const units = integer + decimals + zeroes ;
182191 const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${ decimalPlace } )` ;
183192
193+ const validatedBaseUnits = toUint256 ( units , 'premint' ) ;
194+ checkPotentialPremintOverflow ( validatedBaseUnits , decimalPlace ) ;
195+
184196 c . addConstructorArgument ( { type : 'address' , name : 'recipient' } ) ;
185197
186198 const mintLine = `_mint(recipient, ${ units } * 10 ** ${ exp } );` ;
@@ -212,6 +224,24 @@ function addPremint(
212224 }
213225}
214226
227+ /**
228+ * Check for potential premint overflow assuming the user's contract has decimals() = 18
229+ *
230+ * @param baseUnits The base units of the token, before applying power of 10
231+ * @param decimalPlace If positive, the number of assumed decimal places in the least significant digits of `validatedBaseUnits`. Ignored if <= 0.
232+ * @throws OptionsError if the calculated value would overflow uint256
233+ */
234+ function checkPotentialPremintOverflow ( baseUnits : bigint , decimalPlace : number ) {
235+ const assumedExp = decimalPlace <= 0 ? 18 : 18 - decimalPlace ;
236+ const calculatedValue = scaleByPowerOfTen ( baseUnits , assumedExp ) ;
237+
238+ if ( calculatedValue > UINT256_MAX ) {
239+ throw new OptionsError ( {
240+ premint : 'Amount would overflow uint256 after applying decimals' ,
241+ } ) ;
242+ }
243+ }
244+
215245function addMintable ( c : ContractBuilder , access : Access ) {
216246 requireAccessControl ( c , functions . mint , access , 'MINTER' , 'minter' ) ;
217247 c . addFunctionCode ( '_mint(to, amount);' , functions . mint ) ;
0 commit comments